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 是一个应答的观察者,实际上是服务器调用它应答的一个特殊接口。
- 我们使用应答观察者的
onNext()
方法返回结果。 - 我们使用应答观察者的
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;
}
}
开启服务,监听客户端的请求。
- 使用构建器的
forPort()
方法指定我们要用于侦听客户端请求的地址和端口。 - 创建我们的服务实现类的实例
RouteGuideService
并将其传递给构建器的addService()
方法。 - 调用
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/
对复杂属性list,map的处理https://blog.csdn.net/July_whj/article/details/79423459
上一篇: 9、张龙netty学习Grpc