1. 程式人生 > >grpc 建立java服務端以及客戶端示例

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的核心是通過googleproto檔案來進行網路介面的定義,在這裡我們就首先需要建立一個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打印出來的結果