Skip to the content.

首页


gRPC

服务端实现接口并启动一个gRPC服务去处理客户端调用,客户端使用stub提供与服务器相同的方法,gRPC服务可以和stub在不同的环境中运行及通行。

Grpc基于Http2,使用netty进行通行,即服务端启动netty服务器,客户端向服务端发送Http2请求。

protobuf

默认使用protobuf(也可以是JSON),需要定义.proto文件描述数据结构,然后通过插件生成对应语言的代码。

syntax = "proto3"; // 如果不声明则默认为proto2。

import "myproject/other_protos.proto"; // 导入其他proto文件,以使用其定义的结构。

package foo.bar; // 定义proto文件的包名

option java_package = "com.foo.bar"; // 定义生成的java类的包名,不指定则默认为package。
option java_outer_classname = "FooBar"; // 指定外部包装类的类型,默认使用proto文件名转为大驼峰,该类必定会生成。
option java_multiple_files = true; // 为每个结构单独生产类,默认为false,将所有类生成为包装类的内部类。
option optimize_for = CODE_SIZE; // 生成较小的类,通过以来公共类和反射代码实现序列化、转换等其他操作。

// 1. 每个字段都需要指定一个唯一的index作为属性名,最小值为1,1-15只使用一字节(全部字段信息),16-2047使用两字节,无法使用19000-19999。
// 2. 添加【repeated】表示为数组(可以为任意个数),否则为单字段(可以不传)。
// 3. 生成的java代码会为每个message单独生成class文件同时包含builder类。
// 4. 注意没有包装类型,所有属性都会设置默认值,需要注意处理默认值。
message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}

// 不支持对象,但可以通过这种方式实现。
message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
}

repeated MapFieldEntry map_field = N;

enum Corpus {
  CORPUS_UNSPECIFIED = 0; // 枚举中必须定义0,且位于第一个。
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
}

// 会生成服务接口和stub。
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

java code

public class GreeterService extends GreeterImplBase {
    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        responseObserver.onNext(HelloReply.newBuilder().build()); // 发送消息
        responseObserver.onCompleted(); // 结束传送
    }
}

创建服务端实现类

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

启动服务,监听端口。

var ManagedChannel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();

创建客户端通道

GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
HelloReply reply = stub.sayHello(HelloRequest.newBuilder().build());

创建阻塞型stub后,使用stub发起请求。

use JSON


maven

<build> <!--necessary for grpc compile-->
    <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.21.1:exe:${os.detected.classifier}</protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.49.0:exe:${os.detected.classifier}</pluginArtifact>
                <!--指定以下配置将生成的文件输出到源码目录中,默认只会生成到jar包中-->
                <!--指定.proto文件根目录,默认${project.basedir}/src/main/proto-->
                <protoSourceRoot>${project.basedir}/src/main/resources/proto</protoSourceRoot>
                <!--指定.java文件生成目录,默认${project.basedir}/src/main/java-->
                <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                <!--设置是否清空output目录,即是否保留生成的.java文件,默认true。-->
                <clearOutputDirectory>false</clearOutputDirectory>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>