gRPC是Google開源的通用高性能RPC框架,它支持的是使用Protocol Buffers來編寫Service定義,支持較多語言擴平臺而且擁有強大的二進制序列化工具集。與文章《RPC框架實踐之:Apache Thrift》 一文中實踐的另外一種通用RPC框架 Thrift 能經過Generator自動生成對應語言的Service接口相似,gRPC也能 自動地生成 Server和Client的 Service存根(Stub),咱們只須要 一個命令 就能快速搭建起RPC運行環境。java
下面實踐一下gRPC框架,作的事情就是:Client端經過遠程RPC調用Server的獲取時間的接口,從而將服務器時間獲取到本地並顯示。git
相似於以前對於 RPC框架: Thrift 的實踐步驟,下面一一闡述。api
首先建立一個基於Maven的項目: GrpcAPI服務器
pom中加入grpc相關的依賴框架
<dependency> <groupId>io.grpc</groupId> <artifactId>grpc-all</artifactId> <version>1.12.0</version> </dependency>
這個grpc-all包含了不少grpc相關的組件:grpc-netty 、 grpc-protobuf 、grpc-stub 等等
maven
這裏添加兩個Maven插件,目的是後面須要用這些插件來執行Protocol Buffers命令,從而自動生成相關的Stub代碼:ide
os-maven-plugin:生成平臺無關的屬性 protobuf-maven-plugin:執行Protocol Buffers命令並生成Stub代碼庫微服務
<build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.4.1.Final</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.5.0</version> <configuration> <pluginId>grpc-java</pluginId> <protocArtifact>com.google.protobuf:protoc:3.0.2:exe:${os.detected.classifier}</protocArtifact> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.2.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
這裏.proto文件的做用和寫法就和個人前一篇文章《RPC框架實踐之:Apache Thrift》 一文中Thrift所要求的.thrift文件編寫同樣,是有其本身的語法要求的!工具
syntax = "proto3」; // 語法版本 // stub選項 option java_package = "com.hansonwang99.grpc.api」; option java_outer_classname = 「RPCDateServiceApi」; option java_multiple_files = true; // 定義包名,相似於個人文章《RPC框架實踐之:Apache Thrift》中的Thrift的namespace package com.hansonwang99.grpc.api; // 服務接口定義,服務端和客戶端都要遵照該接口進行通訊 service RPCDateService { rpc getDate (RPCDateRequest) returns (RPCDateResponse) {} } // 定義消息(請求) message RPCDateRequest { string userName = 1; } // 定義消息(響應) message RPCDateResponse { string serverDate = 1; }
mvn編譯完成之後,在 target/generated-sources目錄下就能看到根據上面 .proto文件自動轉化生成的 Java代碼Stub性能
代碼生成結果以下所示
好了,既然gRPC-API已經有了,下面能夠分別編寫服務端和客戶端
建立基於Maven的項目:Server
pom中添加 GrpcAPI 依賴
<dependency> <groupId>com.hansonwang99</groupId> <artifactId>GrpcAPI</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency>
接下來一步比較關鍵
public class RPCDateServiceImpl extends RPCDateServiceGrpc.RPCDateServiceImplBase{ @Override public void getDate(RPCDateRequest request, StreamObserver<RPCDateResponse> responseObserver) { RPCDateResponse rpcDateResponse = null; Date now=new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("今天是"+"yyyy年MM月dd日 E kk點mm分」); String nowTime = simpleDateFormat.format( now ); try { rpcDateResponse = RPCDateResponse .newBuilder() .setServerDate( "Welcome " + request.getUserName() + ", " + nowTime ) .build(); } catch (Exception e) { responseObserver.onError(e); } finally { responseObserver.onNext( rpcDateResponse ); } responseObserver.onCompleted(); } }
我想此處重寫的 getDate()方法並不陌生吧,這正是上文 .proto 文件中定義的Service接口。 此處邏輯比較簡單:獲取當前時間,而且將其與請求 RPCDateRequest中提取出的 userName字段進行拼接,而後返回給調用端!造成一個閉環
public class GRPCServer { private static final int port = 9999; public static void main( String[] args ) throws Exception { Server server = ServerBuilder. forPort(port) .addService( new RPCDateServiceImpl() ) .build().start(); System.out.println( "grpc服務端啓動成功, 端口=" + port ); server.awaitTermination(); } }
端口自定義的9999,也就是在該端口監聽。如今能夠當即運行GRPCServer,來啓動服務端
建立基於Maven的項目:Client
pom中依然須要添加 GrpcAPI 依賴
<dependency> <groupId>com.hansonwang99</groupId> <artifactId>GrpcAPI</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency>
public class GRPCClient { private static final String host = 「localhost」; private static final int serverPort = 9999; public static void main( String[] args ) throws Exception { ManagedChannel managedChannel = ManagedChannelBuilder.forAddress( host, serverPort ).usePlaintext().build(); try { RPCDateServiceGrpc.RPCDateServiceBlockingStub rpcDateService = RPCDateServiceGrpc.newBlockingStub( managedChannel ); RPCDateRequest rpcDateRequest = RPCDateRequest .newBuilder() .setUserName(「hansonwang99」) .build(); RPCDateResponse rpcDateResponse = rpcDateService.getDate( rpcDateRequest ); System.out.println( rpcDateResponse.getServerDate() ); } finally { managedChannel.shutdown(); } } }
如今當即啓動 GRPCClient!
還記得咱們的目標嗎?
RPC完成的便是遠程的過程調用,在本實驗中那就是客戶端能夠遠程調用服務端的getDate()過程,並將結果取到客戶端來顯示!
本文實驗代碼在此 → 須要自取:https://gitee.com/hansonwang99/Maven_gRPC
做者其餘一些RPC框架的實踐以下:
做者一些關於容器化、微服務化方面的文章以下:
微服務調用鏈追蹤中心搭建
利用K8S技術棧打造我的私有云連載文章
Docker容器可視化監控中心搭建
利用ELK搭建Docker容器化應用日誌中心
做者更多 務實、能看懂、可復現的 原創文章盡在公衆號 CodeSheep