# grpc **Repository Path**: 502959937/grpc ## Basic Information - **Project Name**: grpc - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2016-01-11 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 关于 grpc , proto3 的实践分享 ## 前言 > 互联网+ , 微服务化---服务模块化,它们之间的数据交互协作方式TCP/IP自定义协议 ,Restful风格,RPC(远程调用)等 > RPC (远程过程调用,远程方法调用)----允许一台电脑上的程序调用另一台电脑的程序,它有标准化的沟通机制, 为了能够实现跨平台,大都采用接口描述性语言(Interface Description Language,IDL),无需关注底层实现,专注业务需求开发 ### [facebook 开发的 apache thrift](https://thrift.apache.org/) > 它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中, 如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等创建高效的、无缝的服务, 其传输数据采用二进制格式 [thrift应用实践demo](https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/) ### [google开发的GRPC](http://www.grpc.io/) > gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计, 基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。 + apache thrift 和 grpc 都采用 IDL来作为沟通机制,[IDL详细介绍请参考第4期序列化方案选择](https://git.suweia.net/chenlei/suwei-talks/tree/master/talks/4) # GRPC 构建 ### 支持多种语言 > gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前, 在GitHub上已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go, 其它语言的版本正在积极开发中,其中 grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言, grpc-java已经支持Android开发。 ### 基于HTTP/2标准设计 > 由于gRPC基于HTTP/2标准设计,所以相对于其他RPC框架,gRPC带来了更多强大功能,如双向流、头部压缩、多复用请求等。 这些功能给移动设备带来重大益处,如节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。 同时,gRPC还能够提高了云端服务和Web应用的性能。gRPC既能够在客户端应用,也能够在服务器端应用, 从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建。 ### gRPC已经应用在Google的云服务和对外提供的API中,其主要应用场景如下: 1. 低延迟、高扩展性、分布式的系统 2. 同云服务器进行通信的移动应用客户端 3. 设计语言独立、高效、精确的新协议 4. 便于各方面扩展的分层设计,如认证、负载均衡、日志记录、监控等 ### gRPC是什么 > 使用gRPC,一个客户端应用程序可以直接调用另一台机器上的服务端应用程序的方法,就好像调用本地方法一样。这使得更容易创建分布式应用程序和服务。 正如很多RPC系统,gRPC是基于定义服务,指定可以远程调用方法的参数和返回类型的概念。在服务器侧,服务端实现该接口并且返回gRPC的客户端来处理客户端调用请求。 在客户端侧,客户端打桩,提供跟服务端一样的方法。 ![grpc_what](pic/grpc_what.png) ## [proto3 编译安装 ](https://github.com/google/protobuf) 1. 编译基础需求 + autoconf + automake + libtool + curl (used to download gmock) 2. 构建 ``` #注意配置依赖 gmock --- (被墙) ./autogen.sh ./configure --prefix=/usr make && make check && make install ``` 3. 编写IDL文件 ``` syntax = "proto3"; option java_multiple_files = true; package pb; // The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloResponse){} } service Test { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloResponse){} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloResponse { string message = 1; } ``` 4. 依赖maven,构建GRPC的编译器 ![编译器](pic/protoc.png) ``` 4.0.0 3.0.0-beta-2 0.9.0 //grpc需求依赖的模块 io.grpc grpc-core ${grpc.version} io.grpc grpc-stub ${grpc.version} io.grpc grpc-protobuf ${grpc.version} io.grpc grpc-netty ${grpc.version} com.google.protobuf protobuf-java ${protobuf.version} com.google.protobuf.nano protobuf-javanano 3.0.0-alpha-5 never false central Central Repository https://repo.maven.apache.org/maven2 protoc-plugin https://dl.bintray.com/sergei-ivanov/maven/ kr.motd.maven os-maven-plugin 1.4.0.Final com.google.protobuf.tools maven-protoc-plugin 0.4.4 grpc-java com.google.protobuf:protoc:3.0.0-beta-2:exe:${os.detected.classifier} io.grpc:protoc-gen-grpc-java:0.9.0:exe:${os.detected.classifier} compile compile-custom ``` ### 生成的对象解析 ``` /** 服务端实现接口 */ public static interface Greeter { public void sayHello(pb.HelloRequest request, io.grpc.stub.StreamObserver responseObserver); } /** * 客户端实现接口 */ public static interface GreeterBlockingClient { public pb.HelloResponse sayHello(pb.HelloRequest request); } /** 调用方法 */ @java.lang.Override public void sayHello(pb.HelloRequest request, io.grpc.stub.StreamObserver responseObserver) { asyncUnaryCall( getChannel().newCall(METHOD_SAY_HELLO, getCallOptions()), request, responseObserver); } } /* 绑定服务 --- * / public static io.grpc.ServerServiceDefinition bindService( final Greeter serviceImpl) { return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME) .addMethod( METHOD_SAY_HELLO, asyncUnaryCall( new io.grpc.stub.ServerCalls.UnaryMethod< pb.HelloRequest, pb.HelloResponse>() { @java.lang.Override public void invoke( pb.HelloRequest request, io.grpc.stub.StreamObserver responseObserver) { serviceImpl.sayHello(request, responseObserver); } })).build(); } } ``` ## 关键代码片段分解 ![结构预览](pic/server-client.png) ### 服务器端 1.服务端包含2个模块:网络模块,服务绑定模块 >ServerBuilder(基于netty构建的HTTP/2) ![服务端网络服务核心模块](pic/serverbuilder.png) >网络模块 ![网络模块代码结构](pic/server.png) ``` /** * handle logic thread pool * 用于执行业务逻辑 */ private static final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() , new NamedThreadFactory("logic-handler")); /** * 启动服务 * * @throws Exception */ public void startGrpc() throws Exception { //init builder initServerBuilder(); //bind service server = nettyServerBuilder.build().start(); //register hook Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { // Use stderr here since the logger may has been reset by its JVM shutdown hook. logger.debug("*** shutting down gRPC server since JVM is shutting down"); if (server != null) { server.shutdown();// shut down } executorService.shutdown(); logger.debug("*** server shut down"); } }); if (logger.isDebugEnabled()) { logger.debug("grpc_server bind service port:" + port); } } /** * 挂起服务,提供持久的对外服务 * @throws InterruptedException */ public void awaitTermination() throws InterruptedException { server.awaitTermination(); } ``` >绑定服务模块 [服务绑定抽象类](pic/bind_service.png) > 简单的逻辑实现(对外服务) ![服务逻辑处理](pic/service.png) ### 客户端 >发送的channel ----ManagedChannel,grpc-java 内建根据权重选择对应的channel实现(netty,okhttp,inprocess) ![channel选择核心代码](pic/channel_chose.png) #### 初始化chanel ``` if (PlatformDependent.isAndroid()) {// android 平台 channel = OkHttpChannelBuilder.forAddress(host, port) .usePlaintext(true) .build(); } else { ManagedChannelBuilder managedChannelBuilder = ManagedChannelBuilder.forAddress(host, port); if (managedChannelBuilder instanceof NettyChannelBuilder) { NettyChannelBuilder nettyChannelBuilder = (NettyChannelBuilder) managedChannelBuilder; //default is TLS // nettyChannelBuilder.negotiationType(NegotiationType.TLS); // try { // nettyChannelBuilder.sslContext(GrpcSslContexts.forClient().build()); // } catch (SSLException e) { // e.printStackTrace(); // } channel = nettyChannelBuilder .usePlaintext(true) .build(); } else if (managedChannelBuilder instanceof InProcessChannelBuilder) { InProcessChannelBuilder inProcessChannelBuilder = (InProcessChannelBuilder) managedChannelBuilder; channel = inProcessChannelBuilder .usePlaintext(true) .build(); } } ``` #### 简单使用 ``` /** * 作为单例对象 */ HelloWorldClient client = new HelloWorldClient("localhost", 50051); //build blocking stub (client)---- GreeterGrpc.GreeterBlockingClient greeterBlockingClient = GreeterGrpc.newBlockingStub(grpcClient.getChannel()); //builder send data HelloRequest request = HelloRequest.newBuilder().setName(name).build(); grpcClient.shutdown(); ``` #### 演示