您的位置:首页 > 其它

rpc框架之gRPC 学习 - hello world

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

一、grpc-contract

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

<?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>yjmyzz.grpc</groupId>
<artifactId>grpc-client</artifactId>
<version>1.0</version>

<dependencies>

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0-beta-1</version>
</dependency>

<dependency>
<groupId>yjmyzz.grpc</groupId>
<artifactId>grpc-contract</artifactId>
<version>1.0</version>
</dependency>

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

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>

</dependencies>

</project>


View Code
Client端代码:

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类似的测试:

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

参考文章:

RPC框架性能基本比较测试

Schema evolution in Avro, Protocol Buffers and Thrift

jvm-serializers

RPC综述 - PB, Thrift, Avro
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: