這幾天工作中需要用到grpc進行互動,找到的相關非常多的中文資料,表示大部分都是抄自官網的,沒什麼自己的理解和解說,導致我花了差不多一整天的工作日才搞明白怎麼回事,這裡我就寫個簡單易懂的方法進行記錄,以備哪天忘記了可以查閱。
首先我們拋棄官網那一套重新來進行操作一遍,我是用的是IDEA具體的IDE這個問題視個人情況而定,首先是千篇一律的建立一個空的maven工程。
這個空的工程建立出來之後我們就可以先配置基礎的maven相關的配置了,這裡我們可以抄襲下官網的相關配置
<name>test-grpc</name> <url>http://maven.apache.org</url> <properties> <grpc.version>1.4.0</grpc.version><!-- CURRENT_GRPC_VERSION --> </properties> <dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</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> <groupId>io.grpc</groupId> <artifactId>grpc-testing</artifactId> <version>${grpc.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> </dependencies> <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> <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins></build>
完成了第一步pom.xml配置以後可以進行嘗試下進行mvn install命令的打包,如果正確的話這個時候就能夠擷取build success的提示資訊,如果這些沒問題的話繼續下一步。
我們知道grpc的核心是通過google的proto檔案來進行網路介面的定義,在這裡我們就首先需要建立一個proto檔案
空的檔案建立在proto目錄下面,之後我們對於這個空白的proto進行寫入需要的內容,具體proto檔案的文法在這裡就不進行介紹了,我們選取一個最簡單的形式
這裡對於這些進行簡單的解釋 syntax是文法,我們這裡採用的額是proto3的風格如果使用proto2的風格那麼string不能單獨使用這裡就會報錯
java_package產生java代碼的package
java_outer_classname 建立的javaBean的檔案名稱
java_multiple_files是否需要多檔案,建立java檔案的時候如果這個選項是true那麼我們的TestInput以及TestOutPut會有兩個獨立的檔案,在一般的工作中一個proto往往會有很多個不同的介面定義,所以在這裡我們就只討論false也就是檔案合一的情況
具體的方法以及bean類的定義一目瞭然不再展開
之後我們參看官網給的教程進行編寫服務端以及用戶端的資訊情況,在寫好proto之後進行mvn install一下就會看到有如下的檔案結構建立出了預設的類
我們將這些類複製到我們java代碼的目錄中去,並且建立兩個空的類testserver以及testclient通過這兩個類來測試用戶端以及服務端,這裡server的代碼主要分為三個部分,main方法就簡單略過
public static void main(String[] args) throws IOException, InterruptedException { final TestServer server = new TestServer(); //啟動server server.start(); //block Server防止關閉 server.blockUntilShutdown(); }
接下來的start方法才是啟動服務的核心
private void start() throws IOException { /* The port on which the server should run */ int port = 50051; //這個部分啟動server server = ServerBuilder.forPort(port) .addService(new TestImpl()) .build() .start();}
而具體的服務實現通過重載TestServiceGrpc對應的testFunction方法完成
static class TestImpl extends TestServiceGrpc.TestServiceImplBase { //基礎TestServiceImplBase這個基礎類實現裡面的對應方法 @Override public void testFunction(testProto.TestInput req, StreamObserver<testProto.TestOutput> responseObserver) { testProto.TestOutput reply = testProto.TestOutput.newBuilder().setKey(" 瓜皮 "+req.getKey()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }}
當然這裡是為了簡化,在實際應用中需要使用獨立的類來對於這個TestServiceGrpc.TestServiceImplBase每個server中的每個方法進行重載和實現
接下來我們需要準備TestClient的相關內容了,將官網擷取的內容進行簡化,發現整個邏輯還是比較簡單的分為兩個方法main方法略過解釋
public static void main(String[] args) throws Exception { TestClient client = new TestClient(); try { String user = "大司馬"; //調用對應的方法 client.test(user); } finally { }}
調用到的test方法基本上也就是初始化並串連發送請求
public void test(String name) { testProto.TestInput request = testProto.TestInput.newBuilder().setKey(name).build(); testProto.TestOutput response; try { Channel channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build(); TestServiceGrpc.TestServiceBlockingStub blockingStub =TestServiceGrpc.newBlockingStub(channel); //調用方法 response = blockingStub.testFunction(request); } catch (StatusRuntimeException e) { return; } logger.info("Greeting: " + response.getKey());}
最終在client列印出來的結果