欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GRPC学习笔记

程序员文章站 2024-03-14 14:16:40
...

一.入门基本rpc

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

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty-shaded</artifactId>
    <version>${grpc.version}</version>
</dependency>

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>${grpc.version}</version>
</dependency>

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>${grpc.version}</version>
</dependency>

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

<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.5.0.Final</version>
    </extension>
  </extensions>
  <plugins>
    <plugin>
      <groupId>org.xolstice.maven.plugins</groupId>
      <artifactId>protobuf-maven-plugin</artifactId>
      <version>0.5.1</version>
      <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.21.0:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

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

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

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

    public void sayQlu(StringValue request, StreamObserver<StringValue> 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

相关标签: grpc

上一篇: 9、张龙netty学习Grpc

下一篇: