Grpc快速实践

Posted 悟初境

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Grpc快速实践相关的知识,希望对你有一定的参考价值。

记录下Grpc使用,从 grpc maven编译插件到客户端服务端实现。

proto和Service定义

src/main/proto/AgentModel.proto

模型定义2个实体,参数和返回值。

syntax = "proto3";
option java_package = "com.jimo.grpc";

message AgentInfo 
  string name = 1;
  sint32 index = 2;


message ReportResponse 
  bool ok = 1;
  string msg = 2;

src/main/proto/AgentService.proto

在服务这边就定义一个report方法。

syntax = "proto3";

option java_package = "com.jimo.grpc";

import "AgentModel.proto";

service Agent 
  rpc report(AgentInfo) returns (ReportResponse) 

编译

加入maven插件,同时编译proto文件和grpc。

        <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:$protoc.version:exe:$os.detected.classifier
                    </protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:$grpc.version:exe:$os.detected.classifier
                    </pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

假如要用离线的proto执行文件,可以换成本地路径:

            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocExecutable>D:\\software\\protoc.exe</protocExecutable>
                    <pluginId>grpc-java</pluginId>
                    <pluginExecutable>D:\\software\\protoc-gen-grpc-java.exe</pluginExecutable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

在命令行运行 mvn compile 可编译出protobuf和grpc的类,结构如下:

└─target
    ├─generated-sources
    │  ├─annotations
    │  └─protobuf
    │      ├─grpc-java
    │      │  └─com
    │      │      └─jimo
    │      │          └─grpc
    │      │                  AgentGrpc.java
    │      │
    │      └─java
    │          └─com
    │              └─jimo
    │                  └─grpc
    │                          AgentModel.java
    │                          AgentService.java

服务端实现

先实现服务的处理逻辑: AgentServiceImpl 继承 GRPC生成的抽象类。

import com.jimo.grpc.AgentGrpc;
import com.jimo.grpc.AgentModel;
import io.grpc.stub.StreamObserver;

public class AgentServiceImpl extends AgentGrpc.AgentImplBase 

    @Override
    public void report(AgentModel.AgentInfo request, StreamObserver<AgentModel.ReportResponse> responseObserver) 
        AgentModel.ReportResponse response = AgentModel.ReportResponse.newBuilder().setOk(true).setMsg(request.getName()).build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    

然后起一个服务:

public static void main(String[] args) throws IOException, InterruptedException 
    Server server = ServerBuilder.forPort(8000)
            .addService(new AgentServiceImpl())
            .build().start();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> 
        try 
            server.shutdown().awaitTermination(10, TimeUnit.SECONDS);
         catch (InterruptedException e) 
            e.printStackTrace();
        
    ));
    System.out.println("Listening on 8000...");
    server.awaitTermination();

客户端实现

客户端一般共用一个 Channel,所以传进来.然后通过 Stub调用。

import com.jimo.grpc.AgentGrpc;
import com.jimo.grpc.AgentModel;
import io.grpc.Channel;

public class AgentClient 

    private final AgentGrpc.AgentBlockingStub stub;

    public AgentClient(Channel channel) 
        stub = AgentGrpc.newBlockingStub(channel);
    

    public void report() 
        AgentModel.ReportResponse res = stub.report(AgentModel.AgentInfo.newBuilder().setName("app01").setIndex(98).build());
        System.out.println("收到回复:" + res);
    

客户端共用一个 Channel的创建和调用:

public static void main(String[] args) throws InterruptedException 

    // channel最好创建一个,可以共用,是线程安全的
    ManagedChannel channel = ManagedChannelBuilder
            .forAddress("localhost", 8000)
            // 默认是SSL/TLS,这里不用
            .usePlaintext()
            .build();

    AgentClient agentClient = new AgentClient(channel);
    agentClient.report();
    agentClient.report();

    // channel默认会等待一段时间关闭,如果不用了最好及时关闭,否则会占用TCP连接
    channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);

更多问题

1、我们需要对请求做拦截,做一些AOP的事情怎么弄?—-用 ClientInterceptor

2、在上面的客户端使用了 AgentGrpc.newBlockingStub(channel),还有好几种Stub,有什么区别,怎么使用?

3、客户端和服务端通信的网络和协议是如何实现的?为什么客户端的Channel会自动关闭?

先把坑埋好。

以上是关于Grpc快速实践的主要内容,如果未能解决你的问题,请参考以下文章

Grpc快速实践

gRPC Java 服务端实现简析

微服务快速实践3-java下开源组件选型

微服务快速实践3-java下开源组件选型

grpc实践-学会grpc就是这么简单

漫谈grpc 3:从实践到原理,带你参透 gRPC