RPC框架——gRPC简单示例

RPC框架——gRPC简单示例

1. 简介

  • Google gRPC 是一款RPC框架
  • 官方网址: gRPC
  • 主要支持: C/C++, C#, Dart, GO, Java, Objective-C, Python, PHP, Ruby, Node.js
  • gRPC主要由2部分构成
    • 远程过程调用
    • 数据序列化/反序列化 (Protocol Buffers)

2. 将*.proto 协议文件转换为语言源文件

  • 安装Maven插件(用于编译*.proto 文件)
    <build>
       <extensions>
           <extension>
               <groupId>kr.motd.maven</groupId>
               <artifactId>os-maven-plugin</artifactId>
               <version>1.6.2</version>
           </extension>
       </extensions>
       <plugins>
           <plugin>
               <groupId>org.xolstice.maven.plugins</groupId>
               <artifactId>protobuf-maven-plugin</artifactId>
               <version>0.6.1</version>
               <configuration>
                   <protocArtifact>com.google.protobuf:protoc:3.10.0:exe:${os.detected.classifier}</protocArtifact>
                   <pluginId>grpc-java</pluginId>
                   <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.25.0:exe:${os.detected.classifier}</pluginArtifact>
               </configuration>
               <executions>
                   <execution>
                       <goals>
                           <goal>compile</goal>
                           <goal>compile-custom</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
    </build>
    
  • 编写 my_protocol.proto文件 (官方IDL说明
    syntax = "proto3";
    
    // 包名
    package com.skey.grpcdemo.grpc;
    
    option java_package = "com.skey.grpcdemo.grpc";
    //option java_outer_classname = "PersonProto";
    option java_multiple_files = true;
    
    // 定义一个JavaBean
    message Person {
        int32 id = 1;
        string name = 2;
        int32 age = 3;
    }
    
    // 定义一个请求
    message MyRequest {
        int32 id = 1;
    }
    
    // 定义一个响应
    message MyResponse {
        int32 statusCode = 1;
        Person person = 2;
    }
    
    // 编译一个RPC服务
    service PersonService {
    
        // 定义一个方法getPeronById,传入MyRequest,返回MyResponse
        rpc getPersonById (MyRequest) returns (MyResponse) {
        }
    
        // 定义一个方法getPersons,传入MyRequest,返回多个MyResponse(同理,你还可以发送多个Request)
        rpc getPersons (MyRequest) returns (stream MyResponse) {
        }
    
    }
    
  • 编译*.proto文件,转化为语言源文件
    • 在main目录下创建proto文件夹,将my_protocol.proto文件放入其中
    • 执行命令 mvn compile
    • maven会自动寻找main/proto/下的*.proto文件,进行编译转换
    • 生成的class文件存放在target/classs/下
    • 生成的源文件存放在target/generated-sources/下

3. 使用 gRPC 编写服务端/客户端

  • 引入Maven依赖(当前版本 1.25.0)
    <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-netty-shaded</artifactId>
       <version>1.25.0</version>
    </dependency>
    <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-protobuf</artifactId>
       <version>1.25.0</version>
    </dependency>
    <dependency>
       <groupId>io.grpc</groupId>
       <artifactId>grpc-stub</artifactId>
       <version>1.25.0</version>
    </dependency>
    
  • 服务端示例
    • PersonServiceImpl.java
      package com.skey.grpcdemo;
      
      import com.skey.grpcdemo.grpc.MyRequest;
      import com.skey.grpcdemo.grpc.MyResponse;
      import com.skey.grpcdemo.grpc.Person;
      import com.skey.grpcdemo.grpc.PersonServiceGrpc;
      import io.grpc.stub.StreamObserver;
      
      /**
       * Description: 服务实现类
       * <br/>
       * Date: 2019/12/18 22:03
       *
       * @author ALion
       */
      public class PersonServiceImpl extends PersonServiceGrpc.PersonServiceImplBase {
      
          @Override
          public void getPersonById(MyRequest request, StreamObserver<MyResponse> responseObserver) {
              System.out.println("PersonServiceImpl.getPersonById");
      
              MyResponse.Builder builder = MyResponse.newBuilder();
      
              int id = request.getId();
              if (id > 105) {
                  // 如果id大于,返回失败的状态码0
                  builder.setStatusCode(0);
              } else {
                  Person person = Person.newBuilder()
                          .setId(id)
                          .setName("laowang")
                          .setAge(28)
                          .build();
      
                  builder.setStatusCode(1).setPerson(person);
              }
      
              responseObserver.onNext(builder.build());
      
              // 消息发送完成
              responseObserver.onCompleted();
          }
      
          @Override
          public void getPersons(MyRequest request, StreamObserver<MyResponse> responseObserver) {
              System.out.println("PersonServiceImpl.getPersons");
      
              for (int i = 0; i < 5; i++) {
                  Person person = Person.newBuilder()
                          .setId(i)
                          .setName("laowang")
                          .setAge(28)
                          .build();
                  MyResponse response = MyResponse.newBuilder()
                          .setStatusCode(1)
                          .setPerson(person)
                          .build();
      
                  responseObserver.onNext(response);
              }
              responseObserver.onCompleted();
          }
      }
      
    • ServerDemo.java
      package com.skey.grpcdemo;
      
      import io.grpc.Server;
      import io.grpc.ServerBuilder;
      
      /**
       * Description: 服务端示例
       * <br/>
       * Date: 2019/12/18 22:15
       *
       * @author ALion
       */
      public class ServerDemo {
      
          public static void main(String[] args) {
              // 构建Server
              Server server = ServerBuilder.forPort(10086)
                      .addService(new PersonServiceImpl())
                      .build();
              try {
                  // 启动
                  server.start();
      
                  // 阻塞Server
                  server.awaitTermination();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
      }
      
  • 客户端示例
    • ClientDemo.java
    package com.skey.grpcdemo;
    
    import com.skey.grpcdemo.grpc.MyRequest;
    import com.skey.grpcdemo.grpc.MyResponse;
    import com.skey.grpcdemo.grpc.PersonServiceGrpc;
    import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    
    import java.util.Iterator;
    
    /**
     * Description: 客户端示例
     * <br/>
     * Date: 2019/12/18 22:15
     *
     * @author ALion
     */
    public class ClientDemo {
    
        public static void main(String[] args) {
            // 构建客户端
            ManagedChannel managedChannel = ManagedChannelBuilder
                    .forAddress("localhost",10086)
                    .usePlaintext()
                    .build();
            PersonServiceGrpc.PersonServiceBlockingStub blockingStub = PersonServiceGrpc.newBlockingStub(managedChannel);
    
            for (int i = 100; i < 107; i++) {
                // 构建Request
                MyRequest request = MyRequest.newBuilder()
                        .setId(i)
                        .build();
                // 发送Request,获得Response
                MyResponse response = blockingStub.getPersonById(request);
    
                // 解析状态码
                if (response.getStatusCode() == 1) {
                    System.out.println(response.getPerson());
                } else {
                    System.out.println("No such person that id = " + i);
                }
    
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            System.out.println("------------------------------------------");
    
            // 返回多个 MyResponse
            MyRequest request = MyRequest.newBuilder()
                    .setId(1)
                    .build();
            Iterator<MyResponse> responseIter = blockingStub.getPersons(request);
            responseIter.forEachRemaining(System.out::println);
    
        }
    
    }
    
发布了128 篇原创文章 · 获赞 45 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/alionsss/article/details/103606208