Java 开发 gRPC 服务和客户端

Posted junjiang3

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 开发 gRPC 服务和客户端相关的知识,希望对你有一定的参考价值。

一、gRPC 简介

gRPC 是Go实现的:一个高性能,开源,将移动和HTTP/2放在首位通用的RPC框架。使用gRPC可以在客户端调用不同机器上的服务端的方法,而客户端和服务端的开发语言和

运行环境可以有很多种,基本涵盖了主流语言和平台。双方交互的协议可以在proto文件中定义,客户端和服务端可以很方便的通过工具生成协议和代理代码。而消息的编码是采

google protocol buffer,数据量小、速度快。

gRPC具有以下特点:

(1)基于 HTTP/2, 继而提供了连接多路复用、Body 和 Header 压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。

(2)支持主流开发语言(C, C++, Python, php, Ruby, NodeJS, C#, Objective-C、Golang、Java)

(3)IDL (Interface Definition Language) 层使用了 Protocol Buffers, 非常适合团队的接口设计

下面我们就通过一个java的例子来看看怎么使用gRPC。

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

新的工程创建出来之后,我们就可以先配置基础的maven相关的配置了,这里我们可以抄袭下官网的相关配置:

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

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

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

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; 

这里注意下:如果客户端和服务端使用的语言不同,例如客户端使用Java,服务端是C++,务必保持 proto文件完全一致。

之后我们参看官网给的教程进行编写服务端以及客户端的信息情况,在写好proto之后进行mvn install一下就会在target文件夹的相应目录下创建出了默认的类

此时,我们只需要将这些类复制到我们java代码的目录中去,并开发服务端和客户端即可。

四、服务端开发

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

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(); 
        } 
    } 

五、客户端开发

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(); 
        } 
    } 
}

 

以上是关于Java 开发 gRPC 服务和客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何在 gRPC 中为 Java 手动生成客户端和服务器代码?

grpc:使用 golang 开发 grpc 服务端和客户端

gRPC 实现原理

java版gRPC实战之七:基于eureka的注册发现

GoLang -- gRPC框架四大服务

java版gRPC实战之六:客户端动态获取服务端地址