grpc是google在github于2015年开源的一款RPC框架,虽然protobuf很早google就开源了,但是google一直没推出正式的开源框架,导致github上基于protobuf的rpc五花八门,国内比较著名的有百度的sofa-pbrpc,但是遗憾的是soft-pbrpc没有对应的java实现版本。rgpc还有一个独立的官网:http://www.grpc.io/,目前已经支持的语言有 CC++JavaGoNode.jsPythonRubyObjective-CPHP 、 C#. grpc最大的特点是基于protobuf + http2 协议,http2协议虽然还未正式定稿,但从目前得知的内容来看,潜力巨大。下面是grpc基本的hello world的示例:

一、grpc-contract

还是按老套路,把服务涉及的对象定义、接口定义抽象出来,下面是项目结构图:

pom.xml的内容如下:

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>yjmyzz.grpc</groupId>
8 <artifactId>grpc-contract</artifactId>
9 <version>1.0</version>
10
11
12 <dependencies>
13
14 <dependency>
15 <groupId>junit</groupId>
16 <artifactId>junit</artifactId>
17 <version>4.10</version>
18 </dependency>
19
20 <dependency>
21 <groupId>com.google.protobuf</groupId>
22 <artifactId>protobuf-java</artifactId>
23 <version>3.0.0-beta-1</version>
24 </dependency>
25
26 <dependency>
27 <groupId>io.grpc</groupId>
28 <artifactId>grpc-all</artifactId>
29 <version>0.8.0</version>
30 </dependency>
31
32 </dependencies>
33
34 <!--下面这个节点可选-->
35 <pluginRepositories>
36 <pluginRepository>
37 <releases>
38 <updatePolicy>never</updatePolicy>
39 </releases>
40 <snapshots>
41 <enabled>false</enabled>
42 </snapshots>
43 <id>central</id>
44 <name>Central Repository</name>
45 <url>https://repo.maven.apache.org/maven2</url>
46 </pluginRepository>
47 <pluginRepository>
48 <id>protoc-plugin</id>
49 <url>https://dl.bintray.com/sergei-ivanov/maven/</url>
50 </pluginRepository>
51 </pluginRepositories>
52
53
54 <build>
55 <extensions>
56 <extension>
57 <groupId>kr.motd.maven</groupId>
58 <artifactId>os-maven-plugin</artifactId>
59 <version>1.4.0.Final</version>
60 </extension>
61 </extensions>
62 <plugins>
63 <!--用于根据proto文件生成java类的插件-->
64 <plugin>
65 <groupId>com.google.protobuf.tools</groupId>
66 <artifactId>maven-protoc-plugin</artifactId>
67 <version>0.4.2</version>
68 <configuration>
69 <protocArtifact>com.google.protobuf:protoc:3.0.0-alpha-3.1:exe:${os.detected.classifier}
70 </protocArtifact>
71 <pluginId>grpc-java</pluginId>
72 <pluginArtifact>io.grpc:protoc-gen-grpc-java:0.8.0:exe:${os.detected.classifier}</pluginArtifact>
73 </configuration>
74 <executions>
75 <execution>
76 <goals>
77 <goal>compile</goal>
78 <goal>compile-custom</goal>
79 </goals>
80 </execution>
81 </executions>
82 </plugin>
83
84 <!--生成源代码jar包的插件(可选)-->
85 <plugin>
86 <artifactId>maven-source-plugin</artifactId>
87 <version>2.4</version>
88 <executions>
89 <execution>
90 <phase>package</phase>
91 <goals>
92 <goal>jar-no-fork</goal>
93 </goals>
94 </execution>
95 </executions>
96 </plugin>
97
98 </plugins>
99 </build>
100 </project>

demo_service_dto.proto内容如下:

syntax = "proto3";

package yjmyzz.grpc.study.dto;

option java_multiple_files = true;
option java_outer_classname = "DemoServiceDto"; message PingRequest {
string in=1;
} message PingResponse {
string out=1;
} message QueryParameter {
int32 ageStart = 1;
int32 ageEnd = 2;
} message Person {
int32 age = 1;
string name = 2;
bool sex=3;
double salary=4;
int32 childrenCount=5;
} message PersonList{
repeated Person items=1;
}

注:grpc要求protobuf必须使用3.0以上版本

demo_service.proto内容如下:

 

mvn install 后,会自动在target下生成相应的java class类

二、grpc-server

pom.xml文件如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>yjmyzz.grpc</groupId>
8 <artifactId>grpc-server</artifactId>
9 <version>1.0</version>
10
11
12 <dependencies>
13 <dependency>
14 <groupId>com.google.protobuf</groupId>
15 <artifactId>protobuf-java</artifactId>
16 <version>3.0.0-beta-1</version>
17 </dependency>
18
19 <dependency>
20 <groupId>yjmyzz.grpc</groupId>
21 <artifactId>grpc-contract</artifactId>
22 <version>1.0</version>
23 </dependency>
24
25 <dependency>
26 <groupId>io.grpc</groupId>
27 <artifactId>grpc-all</artifactId>
28 <version>0.8.0</version>
29 </dependency>
30
31 <dependency>
32 <groupId>junit</groupId>
33 <artifactId>junit</artifactId>
34 <version>4.10</version>
35 </dependency>
36
37 </dependencies>
38
39
40 </project>

先对服务接口提供实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package yjmyzz.grpc.study.service.impl;
 
import io.grpc.stub.StreamObserver;
import yjmyzz.grpc.study.dto.*;
import yjmyzz.grpc.study.service.DemoServiceGrpc;
 
import java.util.ArrayList;
import java.util.List;
 
 
public class DemoServiceImpl implements DemoServiceGrpc.DemoService {
    public void ping(PingRequest pingRequest, StreamObserver<PingResponse> streamObserver) {
        PingResponse reply = PingResponse.newBuilder().setOut("pong => " + pingRequest.getIn()).build();
        streamObserver.onValue(reply);
        streamObserver.onCompleted();
    }
 
    public void getPersonList(QueryParameter queryParameter, StreamObserver<PersonList> streamObserver) {
        //System.out.println(queryParameter.getAgeStart() + "-" + queryParameter.getAgeEnd());
        PersonList.Builder personListBuilder = PersonList.newBuilder();
        Person.Builder builder = Person.newBuilder();
        List<Person> list = new ArrayList<Person>();
        for (short i = 0; i < 10; i++) {
            list.add(builder.setAge(i).setChildrenCount(i).setName("test" + i).setSex(true).build());
        }
        personListBuilder.addAllItems(list);
        streamObserver.onValue(personListBuilder.build());
        streamObserver.onCompleted();
    }
}

和前面thriftavro的helloworld一样,这里的实现只是意思一下,方便测试而已。

grpc的server端是基于Netty的(当然还有OKHttp的实现,详情见github项目主页),下面是server端的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package yjmyzz.grpc.study.server;
 
import io.grpc.ServerImpl;
import io.grpc.inprocess.InProcessServerBuilder;
import io.grpc.netty.NettyServerBuilder;
import yjmyzz.grpc.study.service.DemoServiceGrpc;
import yjmyzz.grpc.study.service.impl.DemoServiceImpl;
 
 
public class DemoServiceServer {
 
    private int port = 50051;
    private ServerImpl server;
 
    private void start() throws Exception {
        server = NettyServerBuilder.forPort(port)
                .addService(DemoServiceGrpc.bindService(new DemoServiceImpl()))
                .build().start();
 
        server = InProcessServerBuilder.forName("testServer")
                .addService(DemoServiceGrpc.bindService(new DemoServiceImpl()))
                .build().start();
 
        System.out.println("Server started, listening on " + port);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("*** shutting down gRPC server since JVM is shutting down");
                DemoServiceServer.this.stop();
                System.out.println("*** server shut down");
            }
        });
    }
 
    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }
 
 
    public static void main(String[] args) throws Exception {
        final DemoServiceServer server = new DemoServiceServer();
        server.start();
    }
 
}

三、grpc-client

pom.xml内容:

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>yjmyzz.grpc</groupId>
8 <artifactId>grpc-client</artifactId>
9 <version>1.0</version>
10
11 <dependencies>
12
13 <dependency>
14 <groupId>com.google.protobuf</groupId>
15 <artifactId>protobuf-java</artifactId>
16 <version>3.0.0-beta-1</version>
17 </dependency>
18
19 <dependency>
20 <groupId>yjmyzz.grpc</groupId>
21 <artifactId>grpc-contract</artifactId>
22 <version>1.0</version>
23 </dependency>
24
25 <dependency>
26 <groupId>io.grpc</groupId>
27 <artifactId>grpc-all</artifactId>
28 <version>0.8.0</version>
29 </dependency>
30
31 <dependency>
32 <groupId>junit</groupId>
33 <artifactId>junit</artifactId>
34 <version>4.10</version>
35 </dependency>
36
37 </dependencies>
38
39 </project>

Client端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package yjmyzz.grpc.study.client;
 
import io.grpc.ChannelImpl;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import yjmyzz.grpc.study.dto.PersonList;
import yjmyzz.grpc.study.dto.PingRequest;
import yjmyzz.grpc.study.dto.PingResponse;
import yjmyzz.grpc.study.dto.QueryParameter;
import yjmyzz.grpc.study.service.DemoServiceGrpc;
 
import java.util.concurrent.TimeUnit;
 
public class DemoServiceClient {
 
    private final ChannelImpl channel;
    private final DemoServiceGrpc.DemoServiceBlockingStub blockingStub;
 
    public DemoServiceClient(String host, int port) {
        channel =
                NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
                        .build();
 
 
        blockingStub = DemoServiceGrpc.newBlockingStub(channel);
    }
 
    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }
 
    public void ping(String name) {
        try {
            System.out.println("Will try to ping " + name + " ...");
            PingRequest request = PingRequest.newBuilder().setIn(name).build();
            PingResponse response = blockingStub.ping(request);
            System.out.println("ping: " + response.getOut());
        catch (RuntimeException e) {
            System.out.println("RPC failed:" + e.getMessage());
            return;
        }
    }
 
    public void getPersonList(QueryParameter parameter) {
        try {
            //System.out.println("Will try to getPersonList " + parameter + " ...");
            PersonList response = blockingStub.getPersonList(parameter);
            //System.out.println("items count: " + response.getItemsCount());
//            for (Person p : response.getItemsList()) {
//                System.out.println(p);
//            }
        catch (RuntimeException e) {
            System.out.println("RPC failed:" + e.getMessage());
            return;
        }
    }
 
 
    public static void main(String[] args) throws Exception {
        DemoServiceClient client = new DemoServiceClient("localhost"50051);
        try {
            client.ping("a");
 
            int max = 100000;
            Long start = System.currentTimeMillis();
 
            for (int i = 0; i < max; i++) {
                client.getPersonList(getParameter());
            }
            Long end = System.currentTimeMillis();
            Long elapse = end - start;
            int perform = Double.valueOf(max / (elapse / 1000d)).intValue();
 
            System.out.print("rgpc " + max + " 次NettyServer调用,耗时:" + elapse + "毫秒,平均" + perform + "次/秒");
        finally {
            client.shutdown();
        }
    }
 
    private static QueryParameter getParameter() {
        return QueryParameter.newBuilder().setAgeStart(5).setAgeEnd(50).build();
    }
}

在笔记本测试的结果:

Will try to ping a ...
ping: pong => a
rgpc 100000 次NettyServer调用,耗时:36409毫秒,平均2746次/秒

基本上在每秒3k次的数量级,相对thrift(1w+)、avro(5k+)来讲,目前的差距还是很明显的,但是新事物成长总是需要时间,再给google一段时间,相信以后会让大家感到惊艳的。

在序列化方面,也做了一个跟之前thrift、avro类似的测试:

1
2
3
4
5
6
7
8
9
10
11
@Test
public void test() throws InvalidProtocolBufferException {
 
    QueryParameter queryParameter = QueryParameter.newBuilder().setAgeStart(1).setAgeEnd(5).build();
    byte[] bytes1 = queryParameter.toByteArray();
    System.out.println("Protobuf 3.0 二进制序列后的byte数组长度:" + bytes1.length);
 
    QueryParameter result = QueryParameter.parseFrom(bytes1);
    System.out.println(queryParameter.getAgeStart() + " - " + result.getAgeStart());
 
}

输出:

Protobuf 3.0 二进制序列后的byte数组长度:4
1 - 1

在2进制序列化后的大小方面,protobuf 3大体跟thrift的TCompactProtocal(大小5)接近,比avro(大小2)略差。

文中示例源码下载:http://code.taobao.org/svn/grpc-demo/

grpc例子的更多相关文章

  1. 用Java开发gRPC服务的例子分析

    本文的代码例子来自:https://github.com/grpc/grpc-java  定义服务 这一步与其他语言完全一样,需要定义gRPC的服务.方法.request和response的类型. 完 ...

  2. gRPC 的route_guide例子

      本文的例子代码在: https://github.com/grpc/grpc-go/tree/master/examples/route_guide 功能就类似目前LBS一样,在每个位置上报一些文 ...

  3. java grpc简单例子

    原文地址:http://blog.csdn.net/jek123456/article/details/53465033 用eclipse新建一个maven项目,Id信息如下 <groupId& ...

  4. gRPC的简单Go例子

    gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发 ...

  5. gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(下)

    第一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html gRPC in ASP.NET Core 3.x -- Protocol Buf ...

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

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

  7. gRPC in ASP.NET Core 3.x -- Protocol Buffer(2)Go语言的例子(上)

    上一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html 建立Go项目 在GOPATH的src下面建立一个文件夹 protobuf-go, ...

  8. gRPC源码分析2-Server的建立

    gRPC中,Server.Client共享的Class不是很多,所以我们可以单独的分别讲解Server和Client的源码. 通过第一篇,我们知道对于gRPC来说,建立Server是非常简单的,还记得 ...

  9. gRPC源码分析0-导读

    gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...

随机推荐

  1. Mac Pro 安装 Sublime Text 3,个性化设置,主题 和 插件 收藏

    1.到官网下载安装包 http://www.sublimetext.com/3 2.附注册码一枚 Sublime Text 3 3126 —– BEGIN LICENSE —– Alexey Plut ...

  2. 关于CDN的认识

    传统的未加缓存服务的访问过程: 用户提交域名→浏览器对域名进行解释→得到目的主机的IP地址→根据IP地址访问发出请求→得到请求数据并回复 由上可见,用户访问未使用CDN缓存网站的过程为: 1).用户向 ...

  3. 提取刷机包内system.new.dat文件

    转换 使用python脚本sdat2img来完成 sdat2img.py system.transfer.list system.new.dat system.img 输出信息 Skipping co ...

  4. 【转】ubuntu 配置 java jdk1.8 环境,增加多版本 jdk 和切换方法

    一.安装java jdk1.8 1.添加软件源 sudo add-apt-repository ppa:webupd8team/java 2.更新软件源 sudo apt-get update 3.安 ...

  5. LVS集群之DR模式 实现

    ps:做 dr 模式 之前,先把之前做过的操作清空掉 1.ipvsadm -ln 查看规则 2.ipvsadm -C 清空规则 3.ipvsadm -ln 确认 4.iptables -t nat - ...

  6. sql之left join、right join、inner join的区别

    sql之left join.right join.inner join的区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括 ...

  7. Linux之tomcat日志管理

    tomcat 的日志输出catalina.out,变大,可使用下面方式解决. cronolog. http://blog.csdn.net/huang_xw/article/details/61942 ...

  8. 学习android推荐网站

    1. Android Developers 作为一个Android开发者,官网的资料当然不可错过,从设计,培训,指南,文档,都不应该错过,在以后的学习过程中慢慢理解体会. 2. Android Gui ...

  9. PCA数据降维

    Principal Component Analysis 算法优缺点: 优点:降低数据复杂性,识别最重要的多个特征 缺点:不一定需要,且可能损失有用的信息 适用数据类型:数值型数据 算法思想: 降维的 ...

  10. JavaOO面向对象中的注意点(二)

    1.封装: 封装主要体现在:组装类 和 信息隐藏. a.信息隐藏:①访问修饰符:private ②方法的实现:get/set方法.run()方法-控制流程 b.组装类: ①类的定义:属性.构造.行为( ...