grpc-java入门实例

曾经终败给现在 2023-07-12 09:21 60阅读 0赞

本文主要介绍如何在Intellij IDEA环境下,快速搭建出grpc-java的入门实例。这个入门实例是一个HelloWorld程序,客户端发送world到服务端,服务端接收到请求后,拼装成 Hello,world返回。

环境配置
JDK1.8
Maven 3.6
Intellij IDEA

创建一个Project

使用Maven自带的maven-archetype-webapp原型创建一个webapp项目,在src/main下新建对应的java和proto文件夹,并将java文件夹转换为 Source Root,项目结构如下图所示:
grpc-java demo

pom文件中引入相关依赖和插件

  1. <dependency>
  2. <groupId>io.grpc</groupId>
  3. <artifactId>grpc-netty-shaded</artifactId>
  4. <version>1.27.2</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.grpc</groupId>
  8. <artifactId>grpc-protobuf</artifactId>
  9. <version>1.27.2</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>io.grpc</groupId>
  13. <artifactId>grpc-stub</artifactId>
  14. <version>1.27.2</version>
  15. </dependency>
  16. <build>
  17. <finalName>grpc-java</finalName>
  18. <extensions>
  19. <extension>
  20. <groupId>kr.motd.maven</groupId>
  21. <artifactId>os-maven-plugin</artifactId>
  22. <version>1.6.2</version>
  23. </extension>
  24. </extensions>
  25. <plugins>
  26. <plugin>
  27. <groupId>org.xolstice.maven.plugins</groupId>
  28. <artifactId>protobuf-maven-plugin</artifactId>
  29. <version>0.6.1</version>
  30. <configuration>
  31. <protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier}</protocArtifact>
  32. <pluginId>grpc-java</pluginId>
  33. <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.27.2:exe:${os.detected.classifier}</pluginArtifact>
  34. </configuration>
  35. <executions>
  36. <execution>
  37. <goals>
  38. <goal>compile</goal>
  39. <goal>compile-custom</goal>
  40. </goals>
  41. </execution>
  42. </executions>
  43. </plugin>
  44. </plugins>
  45. </build>

编写.proto文件,定义服务接口

在proto文件夹下编写一个helloworld.proto文件,内容如下:

  1. syntax = "proto3";
  2. option java_multiple_files = true;
  3. option java_package = "io.grpc.examples.helloworld";
  4. option java_outer_classname = "HelloWorldProto";
  5. option objc_class_prefix = "HLW";
  6. package helloworld;
  7. // The greeting service definition.
  8. service Greeter {
  9. // Sends a greeting
  10. rpc SayHello (HelloRequest) returns (HelloReply) {}
  11. }
  12. // The request message containing the user's name.
  13. message HelloRequest {
  14. string name = 1;
  15. }
  16. // The response message containing the greetings
  17. message HelloReply {
  18. string message = 1;
  19. }

通过protocol buffer编译器生成服务端和客户端代码

选中Project,执行Maven Compile操作,会在target/generate-sources下生成对应的代码。
grpc-java proto buffer

使用Java gRPC API为上面定义的服务接口编写客户端和服务端

在src/main/java文件夹下新建,io.grpc.examples.helloworldPackage,并将代码放在此文件夹下,与helloworld.proto文件中指定的java_package参数对应。(如果放在其它文件夹下,代码要做适当调整,因为代码的引用位置变了)。

客户端代码
HelloWorldClient.java

  1. public class HelloWorldClient {
  2. private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());
  3. private final ManagedChannel channel;
  4. private final GreeterGrpc.GreeterBlockingStub blockingStub;
  5. /** Construct client connecting to HelloWorld server at {@code host:port}. */
  6. public HelloWorldClient(String host, int port) {
  7. this(ManagedChannelBuilder.forAddress(host, port)
  8. // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
  9. // needing certificates.
  10. .usePlaintext()
  11. .build());
  12. }
  13. /** Construct client for accessing HelloWorld server using the existing channel. */
  14. HelloWorldClient(ManagedChannel channel) {
  15. this.channel = channel;
  16. blockingStub = GreeterGrpc.newBlockingStub(channel);
  17. }
  18. public void shutdown() throws InterruptedException {
  19. channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
  20. }
  21. /** Say hello to server. */
  22. public void greet(String name) {
  23. logger.info("Will try to greet " + name + " ...");
  24. HelloRequest request = HelloRequest.newBuilder().setName(name).build();
  25. HelloReply response;
  26. try {
  27. response = blockingStub.sayHello(request);
  28. } catch (StatusRuntimeException e) {
  29. logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
  30. return;
  31. }
  32. logger.info("Greeting: " + response.getMessage());
  33. }
  34. /**
  35. * Greet server. If provided, the first element of {@code args} is the name to use in the
  36. * greeting.
  37. */
  38. public static void main(String[] args) throws Exception {
  39. // Access a service running on the local machine on port 50051
  40. HelloWorldClient client = new HelloWorldClient("localhost", 50051);
  41. try {
  42. String user = "world";
  43. // Use the arg as the name to greet if provided
  44. if (args.length > 0) {
  45. user = args[0];
  46. }
  47. client.greet(user);
  48. } finally {
  49. client.shutdown();
  50. }
  51. }
  52. }

服务端代码
HelloWorldServer.java

  1. public class HelloWorldServer {
  2. private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
  3. private Server server;
  4. private void start() throws IOException {
  5. /* The port on which the server should run */
  6. int port = 50051;
  7. server = ServerBuilder.forPort(port)
  8. .addService(new GreeterImpl())
  9. .build()
  10. .start();
  11. logger.info("Server started, listening on " + port);
  12. Runtime.getRuntime().addShutdownHook(new Thread() {
  13. @Override
  14. public void run() {
  15. // Use stderr here since the logger may have been reset by its JVM shutdown hook.
  16. System.err.println("*** shutting down gRPC server since JVM is shutting down");
  17. try {
  18. HelloWorldServer.this.stop();
  19. } catch (InterruptedException e) {
  20. e.printStackTrace(System.err);
  21. }
  22. System.err.println("*** server shut down");
  23. }
  24. });
  25. }
  26. private void stop() throws InterruptedException {
  27. if (server != null) {
  28. server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
  29. }
  30. }
  31. /**
  32. * Await termination on the main thread since the grpc library uses daemon threads.
  33. */
  34. private void blockUntilShutdown() throws InterruptedException {
  35. if (server != null) {
  36. server.awaitTermination();
  37. }
  38. }
  39. /**
  40. * Main launches the server from the command line.
  41. */
  42. public static void main(String[] args) throws IOException, InterruptedException {
  43. final HelloWorldServer server = new HelloWorldServer();
  44. server.start();
  45. server.blockUntilShutdown();
  46. }
  47. static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
  48. @Override
  49. public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
  50. HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
  51. responseObserver.onNext(reply);
  52. responseObserver.onCompleted();
  53. }
  54. }
  55. }

执行代码

先运行HelloWorldServer,再运行HelloWorldClient,结果如下:
HelloWorldServer
HelloWorldClient
有兴趣的话可以改改这个示例,然后看看运行效果。

注意:
如果想在Eclipse环境运行该实例,需要注意以下几个不同点:

  1. pom文件中插件引用
    Intellij中:



    kr.motd.maven
    os-maven-plugin
    1.6.2

eclipse中:

  1. <plugin>
  2. <groupId>kr.motd.maven</groupId>
  3. <artifactId>os-maven-plugin</artifactId>
  4. <version>1.6.1</version>
  5. <executions>
  6. <execution>
  7. <phase>initialize</phase>
  8. <goals>
  9. <goal>detect</goal>
  10. </goals>
  11. </execution>
  12. </executions>
  13. </plugin>
  1. .proto文件经过IDE编译后生成的代码引用问题
    Intellij中可以直接引用target目录下生成的protobuf代码,eclipse下不行,需要将生成的文件copy到src/main/java对应的文件夹下(和.proto中配置的java_package参数一致)。另外,因为jdk编译版本的问题,文件copy过后,需要去掉一些@java.lang.Override,否则代码报错(网上查阅资料,jdk高与1.6版本后就会有这个问题,具体没有测试过)。

参考资料
gRPC Quick Start
grpc-java源码地址

-—————-本文结束感谢您的阅读——————

发表评论

表情:
评论列表 (有 0 条评论,60人围观)

还没有评论,来说两句吧...

相关阅读