zoukankan      html  css  js  c++  java
  • grpc例子

    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内容如下:

     View Code

    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/

  • 相关阅读:
    vue中$router和$route的区别
    移动端rem自适应
    如何用Mac自带的QuickTime Player录制视频并制作GIF动图
    vue页面刷新重定向
    JavaScript Functional Programming:声明式与命令式
    配置一个可以使用Vue的History模式的后端服务
    vue使用jsx语法开发
    vue多页面项目配置
    JavaScript的本来面貌之默认结构
    JavaScript的本来面貌之默认值
  • 原文地址:https://www.cnblogs.com/hujihon/p/6023660.html
Copyright © 2011-2022 走看看