Java 开发 gRPC 服务和客户端

新建一个普通的Maven项目:

Java 开发 gRPC 服务和客户端

Java 开发 gRPC 服务和客户端

Java 开发 gRPC 服务和客户端

配置pom文件,导入gRPC的依赖和插件

pom 中增加外部依赖

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-all</artifactId>
    <version>0.13.2</version>
</dependency>

 

注意,下面的增加 maven 插件: protobuf-maven-plugin:  protobuf 的插件,不是  gRPC的插件,产生的代码只会是 protobuf 序列化、反序列化的代码,没有gRPC通讯部分的代码。

增加 maven 插件: protobuf-maven-plugin: 配置

<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>
<!--
The version of protoc must match protobuf-java. If you don't depend on
protobuf-java directly, you will be transitively depending on the
protobuf-java version that grpc depends on.
-->
<protocArtifact>com.google.protobuf:protoc:3.0.0-beta-2:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:0.13.2:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
完整的 pom 文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ghj1976</groupId>

    <artifactId>myGRPCDemo2</artifactId>

    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <dependency>

            <groupId>io.grpc</groupId>

            <artifactId>grpc-all</artifactId>

            <version>0.13.2</version>

        </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>

                    <!--

                      The version of protoc must match protobuf-java. If you don't depend on

                      protobuf-java directly, you will be transitively depending on the

                      protobuf-java version that grpc depends on.

                    -->

                    <protocArtifact>com.google.protobuf:protoc:3.0.0-beta-2:exe:${os.detected.classifier}</protocArtifact>

                    <pluginId>grpc-java</pluginId>

                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:0.13.2:exe:${os.detected.classifier}</pluginArtifact>

                </configuration>

                <executions>

                    <execution>

                        <goals>

                            <goal>compile</goal>

                            <goal>compile-custom</goal>

                        </goals>

                    </execution>

                </executions>

            </plugin>

        </plugins>

    </build>

</project>

 

编写 proto 文件,并编译产生对应的 java文件

简单期间这里直接用的 helloworld.proto 文件,内容如下:

// Copyright 2015, Google Inc.

// All rights reserved.

//

// Redistribution and use in source and binary forms, with or without

// modification, are permitted provided that the following conditions are

// met:

//

//     * Redistributions of source code must retain the above copyright

// notice, this list of conditions and the following disclaimer.

//     * Redistributions in binary form must reproduce the above

// copyright notice, this list of conditions and the following disclaimer

// in the documentation and/or other materials provided with the

// distribution.

//     * Neither the name of Google Inc. nor the names of its

// contributors may be used to endorse or promote products derived from

// this software without specific prior written permission.

//

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

syntax = "proto3";

option java_multiple_files = true;

option java_package = "io.grpc.examples.helloworld";

option java_outer_classname = "HelloWorldProto";

option objc_class_prefix = "HLW";

package helloworld;

// The greeting 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;

}

 

生成 protobuf 序列化和反序列化代码

注意,这里我们使用的maven 插件是 protobuf的插件,只能产生protobuf的序列化和反序列化的代码,不能产生gRPC通讯的代码。

如果我们只需要产生这部分代码是,才需要使用这个插件。

这个插件的用法参考下图:

Java 开发 gRPC 服务和客户端

如果用命令行生成,则命令是:

$ protoc --java_out=./java/ ./proto/helloworld.proto

生成 gRPC 通讯部分代码

这时候我们应该使用的是 protoc-gen-grpc-java插件。

这个插件的获取和编译方法请参考: http://www.cnblogs.com/ghj1976/p/5454881.html 

我们这时候产生对应java代码的命令如下:

$ protoc --plugin=protoc-gen-grpc-java=/Users/ghj1976/project/github/grpc/grpc-java/compiler/build/exe/java_plugin/protoc-gen-grpc-java --grpc-java_out=./java/ ./proto/helloworld.proto

这两部生成的文件如下:

Java 开发 gRPC 服务和客户端

GreeterGrpc.java  是 protoc-gen-grpc-java 插件生成的, 其他文件时 protoc 生成的。

 

编写服务器端代码

我们服务器端的代码如下, 生成的文件在io.grpc.examples.helloworld, 我们的服务器端代码在 com.ghj1976 :

package com.ghj1976;

import io.grpc.Server;

import io.grpc.ServerBuilder;

import io.grpc.examples.helloworld.GreeterGrpc;

import io.grpc.examples.helloworld.HelloReply;

import io.grpc.examples.helloworld.HelloRequest;

import io.grpc.stub.StreamObserver;

import java.io.IOException;

import java.util.logging.Logger;

/**

* Created by ghj1976 on 16/5/4.

*/

public class HelloWorldServer {

    private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());

    private int port = 50051;

    private Server server;

    private void start() throws IOException{

        server = ServerBuilder.forPort(port)

                .addService(new GreeterImpl())

                .build()

                .start();

        logger.info("Server started, listening on "+ port);

        Runtime.getRuntime().addShutdownHook(new Thread(){

            @Override

            public void run(){

                System.err.println("*** shutting down gRPC server since JVM is shutting down");

                HelloWorldServer.this.stop();

                System.err.println("*** server shut down");

            }

        });

    }

    private void stop(){

        if (server != null){

            server.shutdown();

        }

    }

    // block 一直到退出程序

    private void blockUntilShutdown() throws InterruptedException {

        if (server != null){

            server.awaitTermination();

        }

    }

    public  static  void main(String[] args) throws IOException, InterruptedException {

        final HelloWorldServer server = new HelloWorldServer();

        server.start();

        server.blockUntilShutdown();

    }

    // 实现 定义一个实现服务接口的类

    private class GreeterImpl extends GreeterGrpc.AbstractGreeter {

        @Override

        public void sayHello(HelloRequest req,StreamObserver<HelloReply> responseObserver){

            HelloReply reply = HelloReply.newBuilder().setMessage(("Hello "+req.getName())).build();

            responseObserver.onNext(reply);

            responseObserver.onCompleted();

        }

    }

}

运行 这个类的 main 方法,就可以在 50051 端口启动服务。

go实现的服务器端代码在:

https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_server/main.go 

编写客户端代码

 

为了实现跨语言的调用,我们可以用下面 go 实现的客户端来试验。

https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go 

 

如果用 Java 写客户端的话,则是下面代码:

package com.ghj1976;

import io.grpc.ManagedChannel;

import io.grpc.ManagedChannelBuilder;

import io.grpc.StatusRuntimeException;

import io.grpc.examples.helloworld.GreeterGrpc;

import io.grpc.examples.helloworld.HelloReply;

import io.grpc.examples.helloworld.HelloRequest;

import java.util.concurrent.TimeUnit;

import java.util.logging.Level;

import java.util.logging.Logger;

/**

* Created by ghj1976 on 16/5/4.

*/

public class HelloWorldClient {

    private final ManagedChannel channel;

    private final GreeterGrpc.GreeterBlockingStub blockingStub;

    private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());

    public HelloWorldClient(String host,int port){

        channel = ManagedChannelBuilder.forAddress(host,port)

                .usePlaintext(true)

                .build();

        blockingStub = GreeterGrpc.newBlockingStub(channel);

    }

    public void shutdown() throws InterruptedException {

        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);

    }

    public  void greet(String name){

        HelloRequest request = HelloRequest.newBuilder().setName(name).build();

        HelloReply response;

        try{

            response = blockingStub.sayHello(request);

        } catch (StatusRuntimeException e)

        {

            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());

            return;

        }

        logger.info("Greeting: "+response.getMessage());

    }

    public static void main(String[] args) throws InterruptedException {

        HelloWorldClient client = new HelloWorldClient("127.0.0.1",50051);

        try{

            String user = "world";

            if (args.length > 0){

                user = args[0];

            }

            client.greet(user);

        }finally {

            client.shutdown();

        }

    }

}

上一篇:详细讲解Hadoop源码阅读工程(以hadoop-2.6.0-src.tar.gz和hadoop-2.6.0-cdh5.4.5-src.tar.gz为代表)


下一篇:grpc(3):使用 golang 开发 grpc 服务端和client