grpc 建立java服務端以及客戶端示例
這幾天工作中需要用到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打印出來的結果