使用gRPC搭建Server端與Client端
gRPC簡介
gRPC是一種RPC框架技術,采用Protocal Buffers(協議緩存) 作為其接口定義的語言(就是Proto來寫接口)和基礎的消息交換格式。
在gRPC中,客戶端應用程序可以直接調用不同機器上的服務器應用程序上的方法,就像它是本地對象一樣,使您可以更輕松地創建分布式應用程序和服務。與許多RPC系統一樣,gRPC基於定義服務的思想,指定可以使用其參數和返回類型遠程調用的方法。在服務器端,服務器實現此接口並運行gRPC服務器來處理客戶端調用。在客戶端,客戶端有一個存根(Stub在某些語言中稱為客戶端),它提供與服務器相同的方法。
gRPC客戶端和服務器可以在各種環境中相互運行和通信 - 從Google內部的服務器到您自己的桌面 - 並且可以使用任何gRPC支持的語言編寫。
使用協議緩存區(Protocal Buffers )
正如您將在我們的示例中更詳細地看到的那樣,您可以在普通的proto文件中定義gRPC服務,並將RPC方法參數和返回類型指定為協議緩沖區消息:
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user‘s name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
這裏我們將采用protoc
特殊的gRPC插件從proto文件生成代碼。但是,使用gRPC插件,您可以生成gRPC客戶端和服務器代碼,十分方便
搭建項目
maven配置文件:
1 <properties> 2註意:這裏的 protoc.version 和 protobuf.version 需要保持一致<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 3 <grpc.version>1.13.1</grpc.version><!-- CURRENT_GRPC_VERSION --> 4 <protobuf.version>3.5.1</protobuf.version> 5 <protoc.version>3.5.1-1</protoc.version> 6 <netty.tcnative.version>2.0.7.Final</netty.tcnative.version> 7 </properties> 8 <dependencies> 9 <dependency> 10 <groupId>io.dropwizard.metrics</groupId> 11 <artifactId>metrics-core</artifactId> 12 <version>4.0.0</version> 13 </dependency> 14 <dependency> 15 <groupId>io.grpc</groupId> 16 <artifactId>grpc-netty</artifactId> 17 <version>${grpc.version}</version> 18 </dependency> 19 <dependency> 20 <groupId>io.grpc</groupId> 21 <artifactId>grpc-protobuf</artifactId> 22 <version>${grpc.version}</version> 23 </dependency> 24 <dependency> 25 <groupId>io.grpc</groupId> 26 <artifactId>grpc-stub</artifactId> 27 <version>${grpc.version}</version> 28 </dependency> 29 <dependency> 30 <groupId>io.grpc</groupId> 31 <artifactId>grpc-alts</artifactId> 32 <version>${grpc.version}</version> 33 </dependency> 34 <dependency> 35 <groupId>io.grpc</groupId> 36 <artifactId>grpc-testing</artifactId> 37 <version>${grpc.version}</version> 38 <scope>test</scope> 39 </dependency> 40 <dependency> 41 <groupId>io.netty</groupId> 42 <artifactId>netty-tcnative-boringssl-static</artifactId> 43 <version>${netty.tcnative.version}</version> 44 </dependency> 45 <dependency> 46 <groupId>com.google.api.grpc</groupId> 47 <artifactId>proto-google-common-protos</artifactId> 48 <version>1.0.0</version> 49 </dependency> 50 <dependency> 51 <groupId>com.google.protobuf</groupId> 52 <artifactId>protobuf-java-util</artifactId> 53 <version>${protobuf.version}</version> 54 </dependency> 55 <dependency> 56 <groupId>junit</groupId> 57 <artifactId>junit</artifactId> 58 <version>4.12</version> 59 <scope>test</scope> 60 </dependency> 61 <dependency> 62 <groupId>org.mockito</groupId> 63 <artifactId>mockito-core</artifactId> 64 <version>1.9.5</version> 65 <scope>test</scope> 66 </dependency> 67 <dependency> 68 <groupId>junit</groupId> 69 <artifactId>junit</artifactId> 70 <version>4.12</version> 71 </dependency> 72 </dependencies> 73 <build> 74 <extensions> 75 <extension> 76 <groupId>kr.motd.maven</groupId> 77 <artifactId>os-maven-plugin</artifactId> 78 <version>1.5.0.Final</version> 79 </extension> 80 </extensions> 81 <plugins> 82 <plugin> 83 <groupId>org.xolstice.maven.plugins</groupId> 84 <artifactId>protobuf-maven-plugin</artifactId> 85 <version>0.5.1</version> 86 <configuration> 87 <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact> 88 <pluginId>grpc-protocol-buffers</pluginId> 89 <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> 90 <!-- 使用自己從官網下的protoc --> 91 <!--<protocExecutable>C:/Users/14687/workspace/google/protoc-3.6.0-win32/bin</protocExecutable>--> 92 </configuration> 93 <executions> 94 <execution> 95 <goals> 96 <goal>compile</goal> 97 <goal>compile-custom</goal> 98 </goals> 99 </execution> 100 </executions> 101 </plugin> 102 <plugin> 103 <groupId>org.apache.maven.plugins</groupId> 104 <artifactId>maven-enforcer-plugin</artifactId> 105 <version>1.4.1</version> 106 <executions> 107 <execution> 108 <id>enforce</id> 109 <goals> 110 <goal>enforce</goal> 111 </goals> 112 <configuration> 113 <rules> 114 <requireUpperBoundDeps/> 115 </rules> 116 </configuration> 117 </execution> 118 </executions> 119 </plugin> 120 <plugin> 121 <groupId>org.apache.maven.plugins</groupId> 122 <artifactId>maven-compiler-plugin</artifactId> 123 <configuration> 124 <source>1.8</source> 125 <target>1.8</target> 126 </configuration> 127 </plugin> 128 </plugins> 129 </build>
編寫.proto文件
在 java 目錄下,新建proto文件,在裏面寫.proto文件,如下:
syntax = "proto3";
option java_package = "com.example.service";
package helloword;
// the greeter service definition
service Greeter {
//send a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
提示:用IDEA可以安裝相應插件:Protobuf Support(File-->setting-->Plugins-->Browse repositories)
編寫server端
1 public class HelloWorldServer { 2 private static final Logger log = Logger.getLogger(HelloWorldServer.class.getName()); 3 4 private Server server; 5 6 public static void main(String[] args) throws IOException, InterruptedException { 7 final HelloWorldServer server = new HelloWorldServer(); 8 server.start(); 9 server.blockUntilShutdown(); 10 } 11 12 private void start() throws IOException { 13 int port = 50051; 14 //1.forPort 指定監聽客戶端請求的端口 15 //2.創建我們的服務端實現類的實例GreeterImpl並將傳遞給構建器的addService方法 16 //3.調用build ()並 start()在構建器上為我們的服務創建和啟動RPC服務器 17 server = ServerBuilder.forPort(port) 18 .addService(new GreeterImpl()) 19 .build() 20 .start(); 21 log.info("Server stated , listener on port:" + port); 22 //JVM關閉時調用的鉤子 23 Runtime.getRuntime().addShutdownHook(new Thread() { 24 @Override 25 public synchronized void start() { 26 System.err.println("*** shutting down gRPC server since JVM is shutting down"); 27 HelloWorldServer.this.stop(); 28 System.err.println("*** server shut down"); 29 } 30 }); 31 } 32 33 private void stop() { 34 if (null != server) { 35 server.shutdown(); 36 } 37 } 38 39 /** 40 * Await termination on the main thread since the grpc library uses daemon threads. 41 * 42 * @throws InterruptedException 43 */ 44 private void blockUntilShutdown() throws InterruptedException { 45 if (null != server) { 46 server.awaitTermination(); 47 } 48 } 49 50 private class GreeterImpl extends GreeterGrpc.GreeterImplBase { 51 /** 52 * @param request 請求 53 * @param responseObserver 響應觀察器 54 */ 55 @Override 56 public void sayHello(HelloRequest request, 57 StreamObserver<HelloReply> responseObserver) { 58 HelloReply reply = HelloReply.newBuilder() 59 .setMessage("Hello" + request.getName()) 60 .build(); 61 //返回 reply數據 62 responseObserver.onNext(reply); 63 //指定完成gRPC的處理 64 responseObserver.onCompleted(); 65 } 66 } 67 }View Code
編寫client端
public class HelloWordClient { private static final Logger log = Logger.getLogger(HelloWordClient.class.getName()); private final ManagedChannel channel; //阻塞/同步 的stub(存根) private final GreeterGrpc.GreeterBlockingStub blockingStub; //非阻塞/異步 的stub private final GreeterGrpc.GreeterStub async; /** * Greet server. If provided, the first element of {@code args} is the name to use in the * greeting. */ public static void main(String[] args) { HelloWordClient client = new HelloWordClient("localhost", 50051); String user = "world"; try { client.greet(user); client.shutdown(); } catch (InterruptedException e) { e.printStackTrace(); } } public HelloWordClient(String host, int port) { this(ManagedChannelBuilder.forAddress(host, port) .usePlaintext() .build()); } public HelloWordClient(ManagedChannel channel) { this.channel = channel; blockingStub = GreeterGrpc.newBlockingStub(channel); async = GreeterGrpc.newStub(channel); } public void greet(String name) { log.info("Will try to greet" + name + ".."); HelloRequest request = HelloRequest.newBuilder().setName(name).build(); HelloReply response = null; try { //使用阻塞 stub調用 response = blockingStub.sayHello(request); } catch (StatusRuntimeException e) { log.info(String.format("rpc failed:%s", e.getStatus())); } log.info("Greeting: " + response.getMessage()); } public void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } }View Code
gRPC官網
GitHub倉庫地址
使用gRPC搭建Server端與Client端