一、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, 非常适合团队的接口设计

二、编写示例工程

  • 下载安装protobuf,过程省略

  • 新建maven项目,过程省略,工程结构

  • 完整的pom.xml

    <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.gm</groupId>
    <artifactId>stream_grpc</artifactId>
    <version>0.0.1-SNAPSHOT</version> <name>stream_grpc</name>
    <url>http://maven.apache.org</url> <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties> <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.1</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-all</artifactId>
    <version>1.17.1</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>
    <protocExecutable>protoc.exe</protocExecutable>
    </configuration>
    <executions>
    <execution>
    <goals>
    <goal>compile</goal>
    <goal>compile-custom</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>
    </project>

    此处需注意protoc的版本,我的为libprotoc 3.4.0,因此选择grpc-all 1.17.1版本

  • 编写 proto 文件

    src/main目录下新建proto目录,新建stream.proto文件,文件可名称任意

    syntax = "proto3";
    package stream;
    service StreamService {
    //简单rpc
    rpc SimpleFun(RequestData) returns (ResponseData){}
    //服务器端流式rpc
    rpc ServerSideStreamFun(RequestData) returns (stream ResponseData){}
    //客户端流式rpc
    rpc ClientSideStreamFun(stream RequestData) returns (ResponseData){}
    //双向流式rpc
    rpc TwoWayStreamFun(stream RequestData) returns (stream ResponseData){}
    }
    message RequestData {
    string text = 1;
    } message ResponseData {
    string text = 1;
    }
  • 编译 protobuf

    执行命令:mvn generate-sourcestarget目下生成下图的文件

  • 文件复制

    src/main/java目录下新建stream包,具体包取决于proto文件中的package名称 ,并java文件复制到新建包中

三、服务类型示例

gRPC存在四种服务类型:

简单rpc

就是一般的rpc调用,一个请求对象对应一个返回对象

  • proto语法,参考stream.proto文件:
    //简单rpc
    rpc SimpleFun(RequestData) returns (ResponseData){}
  • 服务实现
    @Override
    public void simpleFun(RequestData request, StreamObserver<ResponseData> responseObserver) {
    // TODO Auto-generated method stub
    System.out.println("请求参数:" + request.getText());
    responseObserver.onNext(ResponseData.newBuilder().setText("hello gRPC").build());
    responseObserver.onCompleted();
    }
  • server实现,后三种服务类型server实现相同
    package simple.fun;
    
    import java.io.IOException;
    
    import stream.ServiceImpl;
    import stream.StreamServiceGrpc;
    import stream.StreamServiceGrpc.StreamService; public class Server {
    private static int port = 8883;
    private static io.grpc.Server server; public void run() {
    StreamService serviceImpl = new ServiceImpl();
    server = io.grpc.ServerBuilder.forPort(port).addService(StreamServiceGrpc.bindService(serviceImpl)).build();
    try {
    server.start();
    System.out.println("Server start success on port:" + port);
    server.awaitTermination();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } public static void main(String[] args) {
    Server server = new Server();
    server.run();
    }
    }
  • client实现
    package simple.fun;
    
    import java.io.FileNotFoundException;
    import java.io.IOException; import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    import stream.Stream.RequestData;
    import stream.Stream.ResponseData;
    import stream.StreamServiceGrpc;
    import stream.StreamServiceGrpc.StreamServiceBlockingStub; public class Client { public static void main(String[] args) throws FileNotFoundException, IOException {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8883).usePlaintext(true).build();
    StreamServiceBlockingStub stub = StreamServiceGrpc.newBlockingStub(channel); long start = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
    RequestData requestData = RequestData.newBuilder().setText("hello world").build();
    ResponseData responseData = stub.simpleFun(requestData);
    System.out.println(responseData.getText());
    }
    System.out.println(System.currentTimeMillis() - start + " MS");
    channel.shutdown();
    }
    }
  • 执行结果

服务端流式rpc

一个请求对象,服务端可以传回多个结果对象

  • proto语法,参考stream.proto文件:
    //服务器端流式rpc
    rpc ServerSideStreamFun(RequestData) returns (stream ResponseData){}
  • 服务实现
    @Override
    public void serverSideStreamFun(RequestData request, StreamObserver<ResponseData> responseObserver) {
    // TODO Auto-generated method stub
    System.out.println("请求参数:" + request.getText());
    for (int i = 0; i < 10; i++) {
    responseObserver.onNext(ResponseData.newBuilder().setText("你好" + i).build());
    }
    responseObserver.onCompleted();
    }
  • client实现
    package server.side.stream;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Iterator; import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    import stream.Stream.RequestData;
    import stream.Stream.ResponseData;
    import stream.StreamServiceGrpc;
    import stream.StreamServiceGrpc.StreamServiceBlockingStub; public class Client { public static void main(String[] args) throws FileNotFoundException, IOException {
    RequestData requestData = RequestData.newBuilder().setText("hello world").build();
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8883).usePlaintext(true).build();
    StreamServiceBlockingStub stub = StreamServiceGrpc.newBlockingStub(channel); Iterator<ResponseData> it = stub.serverSideStreamFun(requestData);
    long start = System.currentTimeMillis();
    while (it.hasNext()) {
    System.out.println(it.next().getText());
    }
    channel.shutdown();
    System.out.println(System.currentTimeMillis() - start + " MS"); }
    }
  • 执行结果

    -

客户端流式rpc

客户端传入多个请求对象,服务端返回一个响应结果

  • proto语法,参考stream.proto文件:
    //客户端流式rpc
    rpc ClientSideStreamFun(stream RequestData) returns (ResponseData){}
  • 服务实现
    @Override
    public StreamObserver<RequestData> clientSideStreamFun(StreamObserver<ResponseData> responseObserver) {
    // TODO Auto-generated method stub
    return new StreamObserver<RequestData>() {
    private ResponseData.Builder builder = ResponseData.newBuilder(); @Override
    public void onNext(RequestData value) {
    // TODO Auto-generated method stub
    System.out.println("请求参数:" + value.getText()); } @Override
    public void onError(Throwable t) {
    // TODO Auto-generated method stub } @Override
    public void onCompleted() {
    // TODO Auto-generated method stub
    builder.setText("数据接收完成");
    responseObserver.onNext(builder.build());
    responseObserver.onCompleted();
    } };
    }
  • client实现
    package client.side.stream;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Iterator; import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    import io.grpc.stub.StreamObserver;
    import stream.Stream.RequestData;
    import stream.Stream.ResponseData;
    import stream.StreamServiceGrpc;
    import stream.StreamServiceGrpc.StreamServiceBlockingStub;
    import stream.StreamServiceGrpc.StreamServiceStub; public class Client { public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8883).usePlaintext(true).build();
    StreamServiceStub asyncStub = StreamServiceGrpc.newStub(channel); StreamObserver<ResponseData> responseData = new StreamObserver<ResponseData>() {
    @Override
    public void onNext(ResponseData value) {
    // TODO Auto-generated method stub
    System.out.println(value.getText());
    } @Override
    public void onError(Throwable t) {
    // TODO Auto-generated method stub
    t.printStackTrace();
    } @Override
    public void onCompleted() {
    // TODO Auto-generated method stub
    // 关闭channel
    channel.shutdown();
    }
    }; StreamObserver<RequestData> requestData = asyncStub.clientSideStreamFun(responseData);
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
    requestData.onNext(RequestData.newBuilder().setText("你好" + i).build());
    }
    requestData.onCompleted();
    System.out.println(System.currentTimeMillis() - start + " MS");
    // 由于是异步获得结果,所以sleep 10秒
    Thread.sleep(10000);
    }
    }
  • 执行结果

双向流式rpc

结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象

  • proto语法,参考stream.proto文件:
    //双向流式rpc
    rpc TwoWayStreamFun(stream RequestData) returns (stream ResponseData){}
  • 服务实现
    	@Override
    public StreamObserver<RequestData> twoWayStreamFun(StreamObserver<ResponseData> responseObserver) {
    // TODO Auto-generated method stub
    return new StreamObserver<RequestData>() { @Override
    public void onNext(RequestData value) {
    // TODO Auto-generated method stub
    System.out.println("请求参数:" + value.getText());
    responseObserver.onNext(ResponseData.newBuilder().setText(value.getText() + ",欢迎你的加入").build());
    } @Override
    public void onError(Throwable t) {
    // TODO Auto-generated method stub
    t.printStackTrace();
    } @Override
    public void onCompleted() {
    // TODO Auto-generated method stub
    responseObserver.onCompleted();
    } };
    }
  • client实现
    package two.way.stream;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Iterator; import io.grpc.ManagedChannel;
    import io.grpc.ManagedChannelBuilder;
    import io.grpc.stub.StreamObserver;
    import stream.Stream.RequestData;
    import stream.Stream.ResponseData;
    import stream.StreamServiceGrpc;
    import stream.StreamServiceGrpc.StreamServiceBlockingStub;
    import stream.StreamServiceGrpc.StreamServiceStub; public class Client { public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8883).usePlaintext(true).build();
    StreamServiceStub asyncStub = StreamServiceGrpc.newStub(channel); StreamObserver<ResponseData> responseData = new StreamObserver<ResponseData>() {
    @Override
    public void onNext(ResponseData value) {
    // TODO Auto-generated method stub
    System.out.println(value.getText());
    } @Override
    public void onError(Throwable t) {
    // TODO Auto-generated method stub
    t.printStackTrace();
    } @Override
    public void onCompleted() {
    // TODO Auto-generated method stub
    // 关闭channel
    channel.shutdown();
    }
    }; StreamObserver<RequestData> requestData = asyncStub.twoWayStreamFun(responseData);
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
    requestData.onNext(RequestData.newBuilder().setText("你好" + i).build());
    }
    requestData.onCompleted();
    System.out.println(System.currentTimeMillis() - start + " MS");
    // 由于是异步获得结果,所以sleep 10秒
    Thread.sleep(10000);
    }
    }
  • 执行结果

  • 完整代码

    https://github.com/gm19900510/stream_grpc_java

java gRPC四种服务类型简单示例的更多相关文章

  1. 用一个例子说说gRPC的四种服务方法

    本文通过一个简单的例子来演示这4种类型的使用方法 案例代码:https://github.com/codeAB/grpc-sample-example 目录结构说明 ├── calculator.pr ...

  2. gRPC四种模式、认证和授权实战演示,必赞~~~

    前言 上一篇对gRPC进行简单介绍,并通过示例体验了一下开发过程.接下来说说实际开发常用功能,如:gRPC的四种模式.gRPC集成JWT做认证和授权等. 正文 1. gRPC四种模式服务 以下案例演示 ...

  3. MySQL表的四种分区类型

    MySQL表的四种分区类型 一.什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了. 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表 ...

  4. Prometheus 四种metric类型

    Prometheus的4种metrics(指标)类型: Counter Gauge Histogram Summary 四种指标类型的数据对象都是数字,如果要监控文本类的信息只能通过指标名称或者 la ...

  5. Java的四种内部类

    Java的四种内部类包括如下: 成员内部类 静态内部类 局部内部类 匿名内部类 成员内部类: 定义在另一个类(外部类)的内部,而且与成员方法和属性平级叫成员内部类,......相当于外部类的非静态方法 ...

  6. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  7. C++中四种转换类型的区别

    一.四种转换类型比较: 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可 ...

  8. java中四种引用类型

    java中四种引用类型  今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在 ...

  9. RabbitMQ四种交换机类型介绍

    RabbitMQ  原文地址: https://baijiahao.baidu.com/s?id=1577456875919174629&wfr=spider&for=pc 最新版本的 ...

随机推荐

  1. SQL Server2016 AlwaysOn无域高可用

    https://blog.csdn.net/qq_41981651/article/details/90314817 https://blog.csdn.net/roven257/article/de ...

  2. TNS:could not resolve the connect identifier specified解决办法

    添加环境变量解决:TNS_ADMIN ->> D:\OracleDB\product\11.2.0\dbhome_1\NETWORK\ADMIN

  3. Java内存泄漏分析和预防

    1. 什么是内存泄漏?有什么危害 书面说法: 内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个 ...

  4. NOIP2010提高组真题部分整理(没有关押罪犯)

    目录 \(NOIP2010\)提高组真题部分整理 \(T1\)机器翻译: 题目背景: 题目描述: 输入输出格式: 输入输出样例: 说明: 题解: 代码: \(T2\)乌龟棋 题目背景: 题目描述: 输 ...

  5. 汽车Lin总线特点

    串行通信:线间干扰小,节省线束,传输距离长 单线传输:增强的ISO 9141 (ISO 15765-1),总线电压基于VBAT 最高速率:20kbit/s 单主多从结构,无需仲裁:主节点同时包含主任务 ...

  6. C# 给某个方法设定执行超时时间-2

    var response = RunTaskWithTimeout<ReturnType>( (Func<ReturnType>)); /// <summary> ...

  7. Java学习之==>常用字符串方法

    1.定义字符串 // 定义, 为初始化 String str1; // 定义, 并初始化为null String str2 = null; // 定义, 并初始化为空串 String str3 = & ...

  8. zabbix_server调优

    调整zabbix_server参数    /usr/local/zabbix/etc/zabbix_server.conf StartPollers=160 StartPollersUnreachea ...

  9. sudo apt -y upgrade

    sudo apt -y upgrade     直接upgrade,不再询问y/n 但是如果是sudo apt-get install scilab -y 那么,就不再显示上图中的信息,即当安装包的时 ...

  10. vtkExampleWarpVector和vtkWarpScalar

    vtkWarpVector : deform geometry with vector data vtkWarpVector is a filter that modifies point coord ...