grpc例子

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, PHP 、 C#. grpc最大的特点是基于protobuf + http2 协议,http2协议虽然还未正式定稿,但从目前得知的内容来看,潜力巨大。下面是grpc基本的hello world的示例:
一、grpc-contract
还是按老套路,把服务涉及的对象定义、接口定义抽象出来,下面是项目结构图:
grpc例子
文章图片

pom.xml的内容如下:
grpc例子
文章图片
grpc例子
文章图片

1 2 54.0.0 6 7yjmyzz.grpc 8grpc-contract 91.0 10 11 12 13 14 15junit 16junit 174.10 18 19 20 21com.google.protobuf 22protobuf-java 233.0.0-beta-1 24 25 26 27io.grpc 28grpc-all 290.8.0 30 31 32 33 34 35 36 37 38never 39 40 41false 42 43central 44Central Repository 45https://repo.maven.apache.org/maven2 46 47 48protoc-plugin 49https://dl.bintray.com/sergei-ivanov/maven/ 50 51 52 53 54 55 56 57kr.motd.maven 58os-maven-plugin 591.4.0.Final 60 61 62 63 64 65com.google.protobuf.tools 66maven-protoc-plugin 670.4.2 68 69com.google.protobuf:protoc:3.0.0-alpha-3.1:exe:${os.detected.classifier} 70 71grpc-java 72io.grpc:protoc-gen-grpc-java:0.8.0:exe:${os.detected.classifier} 73 74 75 76 77compile 78compile-custom 79 80 81 82 83 84 85 86maven-source-plugin 872.4 88 89 90package 91 92jar-no-fork 93 94 95 96 97 98 99 100

grpc例子
文章图片
demo_service_dto.proto内容如下:
grpc例子
文章图片
grpc例子
文章图片
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例子
文章图片
注:grpc要求protobuf必须使用3.0以上版本
demo_service.proto内容如下:
grpc例子
文章图片
View Code mvn install 后,会自动在target下生成相应的java class类
grpc例子
文章图片


二、grpc-server
pom.xml文件如下:
grpc例子
文章图片
grpc例子
文章图片
1 2 54.0.0 6 7yjmyzz.grpc 8grpc-server 91.0 10 11 12 13 14com.google.protobuf 15protobuf-java 163.0.0-beta-1 17 18 19 20yjmyzz.grpc 21grpc-contract 221.0 23 24 25 26io.grpc 27grpc-all 280.8.0 29 30 31 32junit 33junit 344.10 35 36 37 38 39 40

grpc例子
文章图片
先对服务接口提供实现:
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 streamObserver) { PingResponse reply = PingResponse.newBuilder().setOut( "pong => " + pingRequest.getIn()).build(); streamObserver.onValue(reply); streamObserver.onCompleted(); } public void getPersonList(QueryParameter queryParameter, StreamObserver streamObserver) { //System.out.println(queryParameter.getAgeStart() + "-" + queryParameter.getAgeEnd()); PersonList.Builder personListBuilder = PersonList.newBuilder(); Person.Builder builder = Person.newBuilder(); List list = new ArrayList(); 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(); } }
和前面thrift、avro的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内容:
grpc例子
文章图片
grpc例子
文章图片
1 2 54.0.0 6 7yjmyzz.grpc 8grpc-client 91.0 10 11 12 13 14com.google.protobuf 15protobuf-java 163.0.0-beta-1 17 18 19 20yjmyzz.grpc 21grpc-contract 221.0 23 24 25 26io.grpc 27grpc-all 280.8.0 29 30 31 32junit 33junit 344.10 35 36 37 38 39

grpc例子
文章图片
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例子】转载于:https://www.cnblogs.com/hujihon/p/6023660.html

    推荐阅读