最近要准备开始测试gRPC框架的接口了,所以特来学习一下gRPC的基础知识。首先我们看一下百科定义定义:
gRPC (gRPC Remote Procedure Calls) 是Google发起的一个开源远程过程调用 (Remote procedure call) 系统。该系统基于 HTTP/2 协议传输,使用Protocol Buffers 作为接口描述语言。
在GitHub有一个示例的项目,但是经过我不断尝试,还是失败了。项目过于复杂,包含了各类使用场景的演示Demo和测试Demo。对于我这个新手菜鸡来讲略微超出我能力范围了。所以在我学完了之后准备写个简单的Demo,给各位同为小白的Tester分享一下。
步骤
首先我总结了三步,以方便各位亲自实践。
- 创建SDK
- 创建服务
- 调用接口
首先,先分享一下相关依赖,除了gRPC
的依赖以外,我们还需要用到2个Maven
构建中用到的插件。
依赖:
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.39.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.39.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.39.0</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
</dependencies>
构建插件:
<build>
<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.17.2:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.39.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
创建SDK
首先呢,我们从定义服务、接口以及对象开始,gRPC通过.proto
文件形式定义的。今天分享一下Java
的版本,所以我先新建了一个Java
工程。然后在main
目录下新建proto
目录,然后在proto
目录下新建一个Hello.proto
的文件。内容如下:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.funtester.fungrpc";
service HelloService {
rpc ExecuteHi(HelloRequest) returns (HelloResponse) {};
}
message HelloRequest {
string name = 1;
int32 age = 2;
}
message HelloResponse {
string msg = 1;
}
然后我们就可以使用Maven插件编译打包,可以直接页面点击的,也可以使用打包命令 mvn clear package
。
这样我们就得到了SDK
的Java包:[INFO] Building jar: /Users/oker/IdeaProjects/fun_grpc/target/fun_grpc-1.0-SNAPSHOT.jar
创建服务端
我们在.proto
文件中定义了服务、接口,要想创建服务,必需先实现服务中的接口。下面是我简单实现了接口com.funtester.fungrpc.HelloServiceGrpc.HelloServiceImplBase#executeHi
方法,这里使用的类继承,需要重写父类方法。
package com.funtester.grpc;
import com.funtester.fungrpc.HelloRequest;
import com.funtester.fungrpc.HelloResponse;
import com.funtester.fungrpc.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void executeHi(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
HelloResponse response = HelloResponse.newBuilder()
.setMsg("你好 " + request.getName())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
然后我们创建gRPC服务的启动入口类:
package com.funtester.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
public class Service {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder
.forPort(8080)
.addService(new HelloServiceImpl())
.build();
server.start();
server.awaitTermination();
}
}
然后我们启动服务。
客户端
客户端这个略微复杂了,我选了一个最简单的创建方式com.funtester.fungrpc.HelloServiceGrpc#newBlockingStub
,后续等我学习掌握了其他方式再来分享。
package com.funtester.grpc;
import com.funtester.fungrpc.HelloRequest;
import com.funtester.fungrpc.HelloResponse;
import com.funtester.fungrpc.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class Client {
public static void main(String[] args) {
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 8080)
.usePlaintext()
.build();
HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub = HelloServiceGrpc.newBlockingStub(managedChannel);
HelloRequest orderRequest = HelloRequest.newBuilder()
.setName("FunTester")
.build();
HelloResponse orderResponse = helloServiceBlockingStub.executeHi(orderRequest);
System.out.println("收到响应: " + orderResponse.getMsg());
managedChannel.shutdown();
}
}
测试
执行上面的用例,可以在控制台看到打印结果:
18:49:53.802 grpc-default-executor-0 用户FunTester来了
已经完美实现了预定目标,后续我会分享Go语言版本的gRPC服务端开发与测试,敬请期待!