Java使用gRPC协议开发服务

64 阅读2分钟

前言

Dubbo2.7.5版本开始支持gRPC协议,Dubbo底层还是依赖于io.grpc,如果你要去看Dubbo关于grpc协议的源码,那么首先需要了解io.grpc,本文通过一个简单的示例,用Java启动一个gRPC的服务,并用Postman发起gRPC调用。

项目配置

新建一个Maven项目,首先导入依赖,这里简单粗暴直接导入all。

  <dependencies>
      <dependency>
          <groupId>io.grpc</groupId>
          <artifactId>grpc-all</artifactId>
          <version>1.56.1</version>
      </dependency>
  </dependencies>

gRPC 使用 Protocol Buffers(简称 proto)文件来定义服务。proto 文件定义了可以通过 gRPC 进行通信的消息格式和服务接口。proto 文件使用一种简洁且可扩展的语法来描述这些消息和接口,并且可以根据需要生成不同语言的代码。
因为我们用的是Java语言,所以需要依赖三方库来帮我们将proto文件生成Java对应的代码。

<build>
      <extensions>
          <extension>
              <groupId>kr.motd.maven</groupId>
              <artifactId>os-maven-plugin</artifactId>
              <version>1.6.2</version>
          </extension>
      </extensions>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.7.0</version>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
              </configuration>
          </plugin>
          <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>
                  <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                  <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
                  <clearOutputDirectory>false</clearOutputDirectory>
              </configuration>
              <executions>
                  <execution>
                      <goals>
                          <goal>compile</goal>
                          <goal>compile-custom</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
      </plugins>
  </build>

属性配置如下:

  <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <protoc.version>3.12.0</protoc.version>
      <grpc.version>1.56.1</grpc.version>
  </properties>

定义服务

gRPC通过proto文件来定义服务,这里给出一个简单示例:HelloService服务有一个say方法。

syntax = "proto3";

option java_multiple_files = true;
option java_package = "org.example.service";
option java_outer_classname = "HelloServiceProto";
option objc_class_prefix = "HLW";

// The greeting service definition.
service HelloService {
  // Sends a greeting
  rpc say (RequestData) returns (ResponseData) {}
}

// The request message containing the user's name.
message RequestData {
  string name = 1;
}

// The response message containing the greetings
message ResponseData {
  string message = 1;
}

然后分别通过mvn protobuf:compilemvn protobuf:compile-custom命令生成对应的bean和service。

实现服务

我们在HelloService.proto文件中定义了我们的服务,然后执行命令生成对应的Java类,接下来需要实现服务逻辑。
新建一个类继承HelloServiceGrpc.HelloServiceImplBase,重写方法即可。

注意:HelloServiceGrpc是插件自动生成的类!!!

public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {

    @Override
    public void say(RequestData request, StreamObserver<ResponseData> responseObserver) {
        System.err.println(request.getName());
        responseObserver.onNext(ResponseData.newBuilder().setMessage("你要返回的数据").build());
        responseObserver.onCompleted();
    }
}

服务启动

通过ServerBuilder构建一个Server实例,将我们的服务实现加入进去,启动即可。

Server server = ServerBuilder
                    .forPort(port)
                    .addService(new HelloServiceImpl())
                    .build()
                    .start();

服务调用

篇幅原因就不写代码去调用服务了,Postman是支持直接调用gRPC服务的。
首先输入服务IP和端口,我本地是127.0.0.1:9001,然后导入proto文件,让Postman知道有哪些服务方法,这里只有一个方法:say
image.png

尾巴

gRPC基于HTTP2协议,借助HTTP2的分帧消息机制,实现了高效的数据传输。底层gRPC使用Netty作为数据传输的工具,确保了性能和可靠性。感兴趣的同学可以去看看gRPC的源码,看看它是怎么处理HTTP2的Frame消息的。