GRPC学习笔记

一.入门基本rpc

1.首先需要导入我们需要的包,pom文件中加入


    io.grpc
    grpc-netty-shaded
    ${grpc.version}



    io.grpc
    grpc-protobuf
    ${grpc.version}



    io.grpc
    grpc-stub
    ${grpc.version}

基于protobuf文件代码生成的插件


  
    
      kr.motd.maven
      os-maven-plugin
      1.5.0.Final
    
  
  
    
      org.xolstice.maven.plugins
      protobuf-maven-plugin
      0.5.1
      
        com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}
        grpc-java
        io.grpc:protoc-gen-grpc-java:1.21.0:exe:${os.detected.classifier}
      
      
        
          
            compile
            compile-custom
          
        
      
    
  

2.编写proto文件

//使用proto3语法
syntax = "proto3";

import "google/protobuf/wrappers.proto";

//代码生成的路径
option java_multiple_files = true;
option java_package = "com.thundersdata.backend.facade.grpc";

//service及里面开发的rpc方法
service GreeterService {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayTest(google.protobuf.Int32Value) returns (google.protobuf.Int32Value) {}
  rpc SayQlu(google.protobuf.StringValue) returns (google.protobuf.StringValue){}
}

message HelloRequest {
   string name = 1;
   int32 age = 2;
}

message HelloReply {
   string message = 1;
}

使用pom文件中加入的插件生成代码。

mvn package的话也会自动生成。

3.编写服务端,开放proto文件中定义的rpc方法,并实现方法的内部逻辑,然后开启服务监听客户端请求。

编写开发rpc方法代码,实现我们服务定义的生成的服务接口。

StreamObserver responseObserver 是一个应答的观察者,实际上是服务器调用它应答的一个特殊接口。
  1. 我们使用应答观察者的 onNext() 方法返回结果。
  2. 我们使用应答观察者的 onCompleted() 方法来指出我们已经完成了和 RPC的交互。
@Service
public class GreeterServiceImpl extends GreeterServiceGrpc.GreeterServiceImplBase implements GreeterService {

    public void sayHello(HelloRequest req, StreamObserver responseObserver) {
        HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }

    public void sayTest(Int32Value id, StreamObserver responseObserver) {
        responseObserver.onNext(id);
        responseObserver.onCompleted();
    }

    public void sayQlu(StringValue request, StreamObserver responseObserver) {
        responseObserver.onNext(request);
        responseObserver.onCompleted();
    }

    public String sayHello(String hello){
        return hello;
    }
}

开启服务,监听客户端的请求。

  1. 使用构建器的forPort()方法指定我们要用于侦听客户端请求的地址和端口。
  2. 创建我们的服务实现类的实例RouteGuideService 并将其传递给构建器的addService()方法。
  3. 调用build()start()在构建器上为我们的服务创建和启动RPC服务器
@Component
public class ServiceServer {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${grpc.port}")
    private int port;

    @Autowired
    private GreeterServiceImpl greeterService;

    private Server server;

    public void start() {
        try{
            server = ServerBuilder.forPort(port)
                    .addService(greeterService)
                    .build()
                    .start();

            logger.info("grpc service start with port {}...", port);

        }catch (IOException e){
            e.printStackTrace();
        }

        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {

                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                ServiceServer.this.stop();
                System.err.println("*** server shut down");
            }
        });
    }


    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    // block 一直到退出程序
    public void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }
}

4.编写客户端,使用存根访问开放的rpc方法。

创建存根

为了调用服务方法,我们需要首先创建一个 存根,或者两个存根:

  • 一个 阻塞/同步 存根:这意味着 RPC 调用等待服务器响应,并且要么返回应答,要么造成异常。
  • blockingStub = RouteGuideGrpc.newBlockingStub(channel); 
  • 一个 非阻塞/异步 存根可以向服务器发起非阻塞调用,应答会异步返回。你可以使用异步存根去发起特定类型的流式调用。
  •  asyncStub = RouteGuideGrpc.newStub(channel);
@Data
public class BasicClient {

    private final ManagedChannel channel;

    private final GreeterServiceGrpc.GreeterServiceBlockingStub greeterService;

    public BasicClient(String host, int port) {
        channel = ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build();

        greeterService = GreeterServiceGrpc.newBlockingStub(channel);
    }

}

5.调用

greeterService = basicClient.getGreeterService();
@Test
public void helloTest() {
    HelloRequest helloRequest = HelloRequest.newBuilder().setAge(20).setName("xiaoming").build();
    HelloReply helloReply = greeterService.sayHello(helloRequest);
    Assert.assertEquals("Hello: xiaoming", helloReply.getMessage());
}

和正常方法调用没有很大区别

附学习网站:

官网:https://grpc.io/docs/tutorials/basic/java/

http://grpc.mydoc.io/?t=60134

对复杂属性list,map的处理https://blog.csdn.net/July_whj/article/details/79423459

你可能感兴趣的:(Spring,boot,java)