使用gRPC搭建Server端与Client端

Posted coding400

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用gRPC搭建Server端与Client端相关的知识,希望对你有一定的参考价值。

    gRPC简介

  gRPC是一种RPC框架技术,采用Protocal Buffers(协议缓存) 作为其接口定义的语言(就是Proto来写接口)和基础的消息交换格式。

  在gRPC中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使您可以更轻松地创建分布式应用程序和服务。与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法。在服务器端,服务器实现此接口并运行gRPC服务器来处理客户端调用。在客户端,客户端有一个存根(Stub在某些语言中称为客户端),它提供与服务器相同的方法。

技术分享图片

  gRPC客户端和服务器可以在各种环境中相互运行和通信 - 从Google内部的服务器到您自己的桌面 - 并且可以使用任何gRPC支持的语言编写。因此,例如,您可以使用Go,Python或Ruby轻松创建Java中的gRPC服务器。此外,最新的Google API将具有gRPC版本的界面,让您可以轻松地在应用程序中构建Google功能。

 

 

    使用协议缓存区(Protocal Buffers )

  

  正如您将在我们的示例中更详细地看到的那样,您可以在普通的proto文件中定义gRPC服务,并将RPC方法参数和返回类型指定为协议缓冲区消息:

   

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user‘s name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

  这里我们将采用protoc特殊的gRPC插件从proto文件生成代码。但是,使用gRPC插件,您可以生成gRPC客户端和服务器代码,十分方便

    搭建项目

  maven配置文件:

  

  1 <properties>
  2         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  3         <grpc.version>1.13.1</grpc.version><!-- CURRENT_GRPC_VERSION -->
  4         <protobuf.version>3.5.1</protobuf.version>
  5         <protoc.version>3.5.1-1</protoc.version>
  6         <netty.tcnative.version>2.0.7.Final</netty.tcnative.version>
  7     </properties>
  8     <dependencies>
  9         <dependency>
 10             <groupId>io.dropwizard.metrics</groupId>
 11             <artifactId>metrics-core</artifactId>
 12             <version>4.0.0</version>
 13         </dependency>
 14         <dependency>
 15             <groupId>io.grpc</groupId>
 16             <artifactId>grpc-netty</artifactId>
 17             <version>${grpc.version}</version>
 18         </dependency>
 19         <dependency>
 20             <groupId>io.grpc</groupId>
 21             <artifactId>grpc-protobuf</artifactId>
 22             <version>${grpc.version}</version>
 23         </dependency>
 24         <dependency>
 25             <groupId>io.grpc</groupId>
 26             <artifactId>grpc-stub</artifactId>
 27             <version>${grpc.version}</version>
 28         </dependency>
 29         <dependency>
 30             <groupId>io.grpc</groupId>
 31             <artifactId>grpc-alts</artifactId>
 32             <version>${grpc.version}</version>
 33         </dependency>
 34         <dependency>
 35             <groupId>io.grpc</groupId>
 36             <artifactId>grpc-testing</artifactId>
 37             <version>${grpc.version}</version>
 38             <scope>test</scope>
 39         </dependency>
 40         <dependency>
 41             <groupId>io.netty</groupId>
 42             <artifactId>netty-tcnative-boringssl-static</artifactId>
 43             <version>${netty.tcnative.version}</version>
 44         </dependency>
 45         <dependency>
 46             <groupId>com.google.api.grpc</groupId>
 47             <artifactId>proto-google-common-protos</artifactId>
 48             <version>1.0.0</version>
 49         </dependency>
 50         <dependency>
 51             <groupId>com.google.protobuf</groupId>
 52             <artifactId>protobuf-java-util</artifactId>
 53             <version>${protobuf.version}</version>
 54         </dependency>
 55         <dependency>
 56             <groupId>junit</groupId>
 57             <artifactId>junit</artifactId>
 58             <version>4.12</version>
 59             <scope>test</scope>
 60         </dependency>
 61         <dependency>
 62             <groupId>org.mockito</groupId>
 63             <artifactId>mockito-core</artifactId>
 64             <version>1.9.5</version>
 65             <scope>test</scope>
 66         </dependency>
 67         <dependency>
 68             <groupId>junit</groupId>
 69             <artifactId>junit</artifactId>
 70             <version>4.12</version>
 71         </dependency>
 72     </dependencies>
 73     <build>
 74         <extensions>
 75             <extension>
 76                 <groupId>kr.motd.maven</groupId>
 77                 <artifactId>os-maven-plugin</artifactId>
 78                 <version>1.5.0.Final</version>
 79             </extension>
 80         </extensions>
 81         <plugins>
 82             <plugin>
 83                 <groupId>org.xolstice.maven.plugins</groupId>
 84                 <artifactId>protobuf-maven-plugin</artifactId>
 85                 <version>0.5.1</version>
 86                 <configuration>
 87                     <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
 88                     <pluginId>grpc-protocol-buffers</pluginId>
 89                     <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
 90                     <!-- 使用自己从官网下的protoc -->
 91                     <!--<protocExecutable>C:/Users/14687/workspace/google/protoc-3.6.0-win32/bin</protocExecutable>-->
 92                 </configuration>
 93                 <executions>
 94                     <execution>
 95                         <goals>
 96                             <goal>compile</goal>
 97                             <goal>compile-custom</goal>
 98                         </goals>
 99                     </execution>
100                 </executions>
101             </plugin>
102             <plugin>
103                 <groupId>org.apache.maven.plugins</groupId>
104                 <artifactId>maven-enforcer-plugin</artifactId>
105                 <version>1.4.1</version>
106                 <executions>
107                     <execution>
108                         <id>enforce</id>
109                         <goals>
110                             <goal>enforce</goal>
111                         </goals>
112                         <configuration>
113                             <rules>
114                                 <requireUpperBoundDeps/>
115                             </rules>
116                         </configuration>
117                     </execution>
118                 </executions>
119             </plugin>
120             <plugin>
121                 <groupId>org.apache.maven.plugins</groupId>
122                 <artifactId>maven-compiler-plugin</artifactId>
123                 <configuration>
124                     <source>1.8</source>
125                     <target>1.8</target>
126                 </configuration>
127             </plugin>
128         </plugins>
129     </build>
    注意:这里的  protoc.version 和   protobuf.version 需要保持一致

    编写.proto文件

  在 java 目录下,新建proto文件,在里面写.proto文件,如下:

  

syntax = "proto3";
option java_package = "com.example.service";
package helloword;
// the greeter service definition
service Greeter {
    //send a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {
    }
}
message HelloRequest {
    string name = 1;
}
message HelloReply {
    string message = 1;
}

  提示:用IDEA可以安装相应插件:Protobuf Support(File-->setting-->Plugins-->Browse repositories)

    编写server端

技术分享图片
 1 public class HelloWorldServer {
 2     private static final Logger log = Logger.getLogger(HelloWorldServer.class.getName());
 3 
 4     private Server server;
 5 
 6     public static void main(String[] args) throws IOException, InterruptedException {
 7         final HelloWorldServer server = new HelloWorldServer();
 8         server.start();
 9         server.blockUntilShutdown();
10     }
11 
12     private void start() throws IOException {
13         int port = 50051;
14         //1.forPort 指定监听客户端请求的端口
15         //2.创建我们的服务端实现类的实例GreeterImpl并将传递给构建器的addService方法
16         //3.调用build ()并 start()在构建器上为我们的服务创建和启动RPC服务器
17         server = ServerBuilder.forPort(port)
18                 .addService(new GreeterImpl())
19                 .build()
20                 .start();
21         log.info("Server stated , listener on port:" + port);
22         //JVM关闭时调用的钩子
23         Runtime.getRuntime().addShutdownHook(new Thread() {
24             @Override
25             public synchronized void start() {
26                 System.err.println("*** shutting down gRPC server since JVM is shutting down");
27                 HelloWorldServer.this.stop();
28                 System.err.println("*** server shut down");
29             }
30         });
31     }
32 
33     private void stop() {
34         if (null != server) {
35             server.shutdown();
36         }
37     }
38 
39     /**
40      * Await termination on the main thread since the grpc library uses daemon threads.
41      *
42      * @throws InterruptedException
43      */
44     private void blockUntilShutdown() throws InterruptedException {
45         if (null != server) {
46             server.awaitTermination();
47         }
48     }
49 
50     private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
51         /**
52          * @param request          请求
53          * @param responseObserver 响应观察器
54          */
55         @Override
56         public void sayHello(HelloRequest request,
57                              StreamObserver<HelloReply> responseObserver) {
58             HelloReply reply = HelloReply.newBuilder()
59                     .setMessage("Hello" + request.getName())
60                     .build();
61             //返回 reply数据
62             responseObserver.onNext(reply);
63             //指定完成gRPC的处理
64             responseObserver.onCompleted();
65         }
66     }
67 }
View Code

    编写client端

技术分享图片
public class HelloWordClient {
    private static final Logger log = Logger.getLogger(HelloWordClient.class.getName());
    private final ManagedChannel channel;
    //阻塞/同步 的stub(存根)
    private final GreeterGrpc.GreeterBlockingStub blockingStub;
    //非阻塞/异步 的stub
    private final GreeterGrpc.GreeterStub async;

    /**
     * Greet server. If provided, the first element of {@code args} is the name to use in the
     * greeting.
     */
    public static void main(String[] args) {
        HelloWordClient client = new HelloWordClient("localhost", 50051);
        String user = "world";
        try {
            client.greet(user);
            client.shutdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public HelloWordClient(String host, int port) {
        this(ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build());
    }

    public HelloWordClient(ManagedChannel channel) {
        this.channel = channel;

        blockingStub = GreeterGrpc.newBlockingStub(channel);
        async = GreeterGrpc.newStub(channel);
    }

    public void greet(String name) {
        log.info("Will try to greet" + name + "..");
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response = null;
        try {
            //使用阻塞 stub调用
            response = blockingStub.sayHello(request);
        } catch (StatusRuntimeException e) {
            log.info(String.format("rpc failed:%s", e.getStatus()));
        }
        log.info("Greeting: " + response.getMessage());
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }
}
View Code

 

gRPC官网

GitHub仓库地址

 

以上是关于使用gRPC搭建Server端与Client端的主要内容,如果未能解决你的问题,请参考以下文章

应用java多线程实现server端与多client之间的通信

如何解决zookeeper client端与server端连接不上的问题

gRPC示例初探实战笔记

带入gRPC:gRPC Streaming, Client and Server

Golang gRPC实现内网穿透

gRPC实践:Server&Client