一. 摘要
此篇文章将用实例介绍grpc四种服务类型中的最普通的单项 rpc。
二. 实践
整体项目如下:
其中cloud-grpc-java为maven项目,cloud-grpc-protos为定义接口项目。
1.通过protobuf定义接口和数据类型
在cloud-grpc-protos文件夹下创建hello.proto,内容如下:
syntax = "proto3";option go_package = "pbfs/hello";option java_multiple_files = true;option java_package = "com.cloud.grpc.hello";option java_outer_classname = "HelloProto";option objc_class_prefix = "HL";package hello;service Hello {rpc SayHello (HelloRequest) returns (HelloResponse) {}}// The request message containing the user's name.message HelloRequest {string name = 1;}// The response message containing the greetingsmessage HelloResponse {string message = 1;}
以上,一个 简单 RPC , 客户端使用存根发送请求到服务器并等待响应返回,就像平常的函数调用一样。定义一个SayHello rpc服务,入参:HelloRequest,返参:HelloResponse
2.maven 配置
创建一个如上图(cloud-grpc-java)的maven项目,pom.xml加入grpc开发相关配置,如下:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.cloud.grpc</groupId><artifactId>java</artifactId><version>1.0.0.0</version><name>java</name><description>Demo project for grpc for java</description><properties><java.version>11</java.version><grpc.version>1.29.0</grpc.version><protobuf.version>3.11.0</protobuf.version></properties><dependencies><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><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.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:${protobuf.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>../cloud-grpc-protos</protoSourceRoot></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build></project>
说明:
3.生成grpc,protobuf相关类
mvn protobuf:compilemvn protobuf:compile-custom
4.编写服务端,并运行
编写HelloServer.java如下
package com.cloud.grpc.java.standard.server;import com.cloud.grpc.hello.HelloGrpc;import com.cloud.grpc.hello.HelloRequest;import com.cloud.grpc.hello.HelloResponse;import io.grpc.Server;import io.grpc.ServerBuilder;import io.grpc.stub.StreamObserver;import java.io.IOException;import java.util.concurrent.TimeUnit;public class HelloServer {private Server server;private void start() throws IOException {/* The port on which the server should run */int port = 50051;server = ServerBuilder.forPort(port).addService(new HelloIml()) //这里可以添加多个模块.build().start();System.out.println("Server started, listening on " + port);Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {// Use stderr here since the logger may have been reset by its JVM shutdown hook.System.err.println("*** shutting down gRPC server since JVM is shutting down");try {HelloServer.this.stop();} catch (InterruptedException e) {e.printStackTrace(System.err);}System.err.println("*** server shut down");}});}private void stop() throws InterruptedException {if (server != null) {server.shutdown().awaitTermination(30, TimeUnit.SECONDS);}}private void blockUntilShutdown() throws InterruptedException {if (server != null) {server.awaitTermination();}}public static void main(String[] args) throws IOException, InterruptedException {final HelloServer server = new HelloServer();server.start();server.blockUntilShutdown();}private static class HelloIml extends HelloGrpc.HelloImplBase{@Overridepublic void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {// super.sayHello(request, responseObserver);HelloResponse helloResponse=HelloResponse.newBuilder().setMessage("Hello "+request.getName()+", I'm Java grpc Server").build();responseObserver.onNext(helloResponse);responseObserver.onCompleted();}}}
通过main函数启动:结果如下:
5.编写,运行客户端
编写HelloClient.java,如下:
package com.cloud.grpc.java.standard.client;import com.cloud.grpc.hello.HelloGrpc;import com.cloud.grpc.hello.HelloRequest;import com.cloud.grpc.hello.HelloResponse;import io.grpc.ManagedChannel;import io.grpc.ManagedChannelBuilder;import java.util.concurrent.TimeUnit;public class HelloClient {//远程连接管理器,管理连接的生命周期private final ManagedChannel channel;private final HelloGrpc.HelloBlockingStub blockingStub;public HelloClient(String host, int port) {//初始化连接channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();//初始化远程服务StubblockingStub = HelloGrpc.newBlockingStub(channel);}public void shutdown() throws InterruptedException {//关闭连接channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);}public String sayHello(String name) {//构造服务调用参数对象HelloRequest request = HelloRequest.newBuilder().setName(name).build();//调用远程服务方法HelloResponse response = blockingStub.sayHello(request);//返回值return response.getMessage();}public static void main(String[] args) throws InterruptedException {HelloClient client = new HelloClient("127.0.0.1", 50051);//服务调用String content = client.sayHello("Java client");//打印调用结果System.out.println(content);//关闭连接client.shutdown();}}
执行main函数,结果如下:
可见已从服务端获取响应。
