grpc

大大的橙子 大大的橙子     2022-11-02     585

关键词:

 GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x,基于Netty 4.x +。GRPC与thrift、avro-rpc等其实在总体原理上并没有太大的区别,简而言之GRPC并没有太多突破性的创新。(如下描述,均基于JAVA语言的实现)

    对于开发者而言:

    1)需要使用protobuf定义接口,即.proto文件

    2)然后使用compile工具生成特定语言的执行代码,比如JAVA、C/C++、Python等。类似于thrift,为了解决跨语言问题。

    3)启动一个Server端,server端通过侦听指定的port,来等待Client链接请求,通常使用Netty来构建,GRPC内置了Netty的支持。

    4)启动一个或者多个Client端,Client也是基于Netty,Client通过与Server建立TCP长链接,并发送请求;Request与Response均被封装成HTTP2的stream Frame,通过Netty Channel进行交互。

 

    对于GRPC的“鼓吹”,本文不多表述,截止到今日,GRPC仍然处于开发阶段,尚没有release版本,而且特性也很多需要补充;GRPC基于protobuf 3.x,但是protobuf 3.x也没有release版本;虽然HTTP2协议已成定局,但尚未被主流web容器包括代理服务器支持,这意味着GRPC在HTTP负载均衡方面尚有欠缺;最终,在短期内我们还不能在production环境中实施,可以做技术储备。不过GRPC的缺点,在将来将会成为它的优点,我们需要时间等待它的成熟。

    1)GRPC尚未提供连接池

    2)尚未提供“服务发现”、“负载均衡”机制

    3)因为基于HTTP2,绝大部多数HTTP Server、Nginx都尚不支持,即Nginx不能将GRPC请求作为HTTP请求来负载均衡,而是作为普通的TCP请求。(nginx将会在1.9版本支持)

    4)GRPC尚不成熟,易用性还不是很理想;就本人而言,我还是希望GRPC能够像hessian一样:无IDL文件,无需代码生成,接口通过HTTP表达。

    5)Spring容器尚未提供整合。

 

    在实际应用中,GRPC尚未完全提供连接池、服务自动发现、进程内负载均衡等高级特性,需要开发人员额外的封装;最大的问题,就是GRPC生成的接口,调用方式实在是不太便捷(JAVA),最起码与thrift相比还有差距,希望未来能够有所改进。

 

一、实例

    1、proto文件

    GRPC并没有创造新的序列化协议,而是使用已有的protobuf;基于protobuf来声明数据模型和RPC接口服务,当然protobuf是一个非常优秀的协议框架。关于protobuf 3.x的相关文档,请参见【protobuf 3

    接下来,我们设计一个sayHello接口,我们将数据模型和RPC接口分别保存在两个文件中。

    1)TestModel.proto

 

Java代码  技术分享图片
  1. syntax = "proto3";  
  2. package com.test.grpc;  
  3. option java_package = "com.test.grpc.service.model";  
  4. message TestRequest  
  5.     string name  = 1;  
  6.     int32 id    = 2;  
  7.   
  8. message TestResponse  
  9.     string message = 1;  
  10.   

 

    2)TestService.proto

Java代码  技术分享图片
  1. syntax = "proto3";  
  2. package com.test.grpc;  
  3. option java_package = "com.test.grpc.service";  
  4. import "TestModel.proto";  
  5. service TestRpcService  
  6.     rpc sayHello(TestRequest) returns (TestResponse);  
  7.   

 

    proto文件中需要注意加上“syntax”,表示使用protobuf 3的语法。

    2、生成JAVA代码

    生成代码,我们最好借助于maven插件,可以在pom文件中增加如下信息:

Java代码  技术分享图片
  1. <pluginRepositories><!-- 插件库 -->  
  2.     <pluginRepository>  
  3.         <id>protoc-plugin</id>  
  4.         <url>https://dl.bintray.com/sergei-ivanov/maven/</url>  
  5.     </pluginRepository>  
  6. </pluginRepositories>  
  7. <build>  
  8.     <extensions>  
  9.         <extension>  
  10.             <groupId>kr.motd.maven</groupId>  
  11.             <artifactId>os-maven-plugin</artifactId>  
  12.             <version>1.4.0.Final</version>  
  13.         </extension>  
  14.     </extensions>  
  15.     <plugins>  
  16.         <plugin>  
  17.             <groupId>com.google.protobuf.tools</groupId>  
  18.             <artifactId>maven-protoc-plugin</artifactId>  
  19.             <version>0.4.4</version>  
  20.             <configuration>  
  21.                 <protocArtifact>com.google.protobuf:protoc:3.0.0-beta-2:exe:$os.detected.classifier</protocArtifact>  
  22.                 <pluginId>grpc-java</pluginId>  
  23.                 <pluginArtifact>io.grpc:protoc-gen-grpc-java:$grpc.version:exe:$os.detected.classifier</pluginArtifact>  
  24.             </configuration>  
  25.             <executions>  
  26.                 <execution>  
  27.                     <goals>  
  28.                         <goal>compile</goal>  
  29.                         <goal>compile-custom</goal>  
  30.                     </goals>  
  31.                 </execution>  
  32.             </executions>  
  33.         </plugin>  
  34.     </plugins>  
  35. </build>  

 

    然后只需要执行“mvn compile”指令即可,此后我们会在项目的target目录下看到生成的classes文件,当然最终我们还是需要将service打成jar包发布的。maven仍然可以帮助我们做这些工作,由.proto生成classes是在compile阶段,那么jar阶段仍然是可以将classes打成jar,只需要借助maven-jar-plugin插件即可。

    3、开发Server端服务(简例)

Java代码  技术分享图片
  1. //server端实现类,扩展原有接口  
  2. public class TestServiceImpl implements TestRpcServiceGrpc.TestRpcService   
  3.   
  4.     @Override  
  5.     public void sayHello(TestModel.TestRequest request, StreamObserver<TestModel.TestResponse> responseObserver)   
  6.         String result = request.getName() + request.getId();  
  7.         TestModel.TestResponse response = TestModel.TestResponse.newBuilder().setMessage(result).build();  
  8.         responseObserver.onNext(response);  
  9.         responseObserver.onCompleted();  
  10.       
  11.   

 

Java代码  技术分享图片
  1. public class TestServer   
  2.   
  3.     public static void main(String[] args) throws Exception  
  4.   
  5.         ServerImpl server = NettyServerBuilder.forPort(50010).addService(TestRpcServiceGrpc.bindService(new TestServiceImpl())).build();  
  6.         server.start();  
  7.         server.awaitTermination();//阻塞直到退出  
  8.       
  9.   

 

    稍后启动TestServer即可。

    4、开发Client端(简例)

Java代码  技术分享图片
  1. public class TestClient   
  2.   
  3.     private final TestRpcServiceGrpc.TestRpcServiceBlockingStub client;  
  4.     public TestClient(String host,int port)   
  5.         ManagedChannel channel =  NettyChannelBuilder.forAddress(host, port).usePlaintext(true).build();  
  6.         client = TestRpcServiceGrpc.newBlockingStub(channel).withDeadlineAfter(60000, TimeUnit.MILLISECONDS);  
  7.       
  8.   
  9.     public String sayHello(String name,Integer id)   
  10.         TestModel.TestRequest request = TestModel.TestRequest.newBuilder().setId(id).setName(name).build();  
  11.         TestModel.TestResponse response = client.sayHello(request);  
  12.         return response.getMessage();  
  13.       
  14.   

 

    然后我们运行即可,代码非常简单,当然无论是Client还是Server端,我们还有其他额外的参数可以配置,我们稍后详细介绍。

 

二、原理解析

    GRPC的Client与Server,均通过Netty Channel作为数据通信,序列化、反序列化则使用Protobuf,每个请求都将被封装成HTTP2的Stream,在整个生命周期中,客户端Channel应该保持长连接,而不是每次调用重新创建Channel、响应结束后关闭Channel(即短连接、交互式的RPC),目的就是达到链接的复用,进而提高交互效率。

 

    1、Server端

    我们通常使用NettyServerBuilder,即IO处理模型基于Netty,将来可能会支持其他的IO模型。Netty Server的IO模型简析:

    1)创建ServerBootstrap,设定BossGroup与workerGroup线程池

    2)注册childHandler,用来处理客户端链接中的请求成帧

    3)bind到指定的port,即内部初始化ServerSocketChannel等,开始侦听和接受客户端链接。

    4)BossGroup中的线程用于accept客户端链接,并转发(轮训)给workerGroup中的线程。

    5)workerGroup中的特定线程用于初始化客户端链接,初始化pipeline和handler,并将其注册到worker线程的selector上(每个worker线程持有一个selector,不共享)

    6)selector上发生读写事件后,获取事件所属的链接句柄,然后执行handler(inbound),同时进行拆封package,handler执行完毕后,数据写入通过,由outbound handler处理(封包)通过链接发出。    注意每个worker线程上的数据请求是队列化的。

    参见源码:SingleThreadEventLoop、NioEventLoop。(请求队列化)

 

    GRPC而言,只是对Netty Server的简单封装,底层使用了PlaintextHandler、Http2ConnectionHandler的相关封装等。具体Framer、Stream方式请参考Http2相关文档。

    1)bossEventLoopGroup:如果没指定,默认为一个static共享的对象,即JVM内所有的NettyServer都使用同一个Group,默认线程池大小为1。

    2)workerEventLoopGroup:如果没指定,默认为一个static共享的对象,线程池大小为coreSize * 2。这两个对象采用默认值并不会带来问题;通常情况下,即使你的application中有多个GRPC Server,默认值也一样能够带来收益。不合适的线程池大小,有可能会是性能受限。

    3)channelType:默认为NioServerSocketChannel,通常我们采用默认值;当然你也可以开发自己的类。如果此值为NioServerSocketChannel,则开启keepalive,同时设定SO_BACKLOG为128;BACKLOG就是系统底层已经建立引入链接但是尚未被accept的Socket队列的大小,在链接密集型(特别是短连接)时,如果队列超过此值,新的创建链接请求将会被拒绝(有可能你在压力测试时,会遇到这样的问题),keepalive和BACKLOG特性目前无法直接修改。

Java代码  技术分享图片
  1. [root@sh149 ~]# sysctl -a|grep tcp_keepalive  
  2. net.ipv4.tcp_keepalive_time = 60  ##单位:秒  
  3. net.ipv4.tcp_keepalive_probes = 9  
  4. net.ipv4.tcp_keepalive_intvl = 75 ##单位:秒  
  5. ##可以在/etc/sysctl.conf查看和修改相关值  
  6. ##tcp_keepalive_time:最后一个实际数据包发送完毕后,首个keepalive探测包发送的时间。  
  7. ##如果首个keepalive包探测成功,那么链接会被标记为keepalive(首先TCP开启了keepalive)  
  8. ##此后此参数将不再生效,而是使用下述的2个参数继续探测  
  9. ##tcp_keepalive_intvl:此后,无论通道上是否发生数据交换,keepalive探测包发送的时间间隔  
  10. ##tcp_keepalive_probes:在断定链接失效之前,尝试发送探测包的次数;  
  11. ##如果都失败,则断定链接已关闭。  

 

    对于Server端,我们需要关注上述keepalive的一些设置;如果Netty Client在空闲一段时间后,Server端会主动关闭链接,有可能Client仍然保持链接的句柄,将会导致RPC调用时发生异常。这也会导致GRPC客户端调用时偶尔发生错误的原因之一。

    4)followControlWindow:流量控制的窗口大小,单位:字节,默认值为1M,HTTP2中的“Flow Control”特性;连接上,已经发送尚未ACK的数据帧大小,比如window大小为100K,且winow已满,每次向Client发送消息时,如果客户端反馈ACK(携带此次ACK数据的大小),window将会减掉此大小;每次向window中添加亟待发送的数据时,window增加;如果window中的数据已达到限定值,它将不能继续添加数据,只能等待Client端ACK。

    5)maxConcurrentCallPerConnection:每个connection允许的最大并发请求数,默认值为Integer.MAX_VALUE;如果此连接上已经接受但尚未响应的streams个数达到此值,新的请求将会被拒绝。为了避免TCP通道的过度拥堵,我们可以适度调整此值,以便Server端平稳处理,毕竟buffer太多的streams会对server的内存造成巨大压力。

    6)maxMessageSize:每次调用允许发送的最大数据量,默认为100M。

    7)maxHeaderListSize:每次调用允许发送的header的最大条数,GRPC中默认为8192。

 

    对于其他的比如SSL/TSL等,可以参考其他文档。

    GRPC Server端,还有一个最终要的方法:addService。【如下文service代理模式】

    在此之前,我们需要介绍一下bindService方法,每个GRPC生成的service代码中都有此方法,它以硬编码的方式遍历此service的方法列表,将每个方法的调用过程都与“被代理实例”绑定,这个模式有点类似于静态代理,比如调用sayHello方法时,其实内部直接调用“被代理实例”的sayHello方法(参见MethodHandler.invoke方法,每个方法都有一个唯一的index,通过硬编码方式执行);bindService方法的最终目的是创建一个ServerServiceDefinition对象,这个对象内部位置一个map,key为此Service的方法的全名(fullname,package.service.method),value就是此方法的GRPC封装类(ServerMethodDefinition)。

    源码分析:

Java代码  技术分享图片
  1. private static final int METHODID_SAY_HELLO = 0;  
  2. private static class MethodHandlers<Req, Resp> implements  
  3.       ...   
  4.     private final TestRpcService serviceImpl;//实际被代理实例  
  5.     private final int methodId;  
  6.   
  7.     public MethodHandlers(TestRpcService serviceImpl, int methodId)   
  8.       this.serviceImpl = serviceImpl;  
  9.       this.methodId = methodId;  
  10.       
  11.   
  12.     @java.lang.SuppressWarnings("unchecked")  
  13.     public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver)   
  14.       switch (methodId)   
  15.         case METHODID_SAY_HELLO:        //通过方法的index来判定具体需要代理那个方法  
  16.           serviceImpl.sayHello((com.test.grpc.service.model.TestModel.TestRequest) request,  
  17.               (io.grpc.stub.StreamObserver<com.test.grpc.service.model.TestModel.TestResponse>) responseObserver);  
  18.           break;  
  19.         default:  
  20.           throw new AssertionError();  
  21.         
  22.       
  23.     ....  
  24.     
  25.   
  26.   public static io.grpc.ServerServiceDefinition bindService(  
  27.       final TestRpcService serviceImpl)   
  28.     return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME)  
  29.         .addMethod(  
  30.           METHOD_SAY_HELLO,  
  31.           asyncUnaryCall(  
  32.             new MethodHandlers<  
  33.               com.test.grpc.service.model.TestModel.TestRequest,  
  34.               com.test.grpc.service.model.TestModel.TestResponse>(  
  35.                 serviceImpl, METHODID_SAY_HELLO)))  
  36.         .build();  
  37.     

 

    addService方法可以添加多个Service,即一个Netty Server可以为多个service服务,这并不违背设计模式和架构模式。addService方法将会把service保存在内部的一个map中,key为serviceName(即package.service),value就是上述bindService生成的对象。

 

    那么究竟Server端是如何解析RPC过程的?Client在调用时会将调用的service名称 + method信息保存在一个GRPC“保留”的header中,那么Server端即可通过获取这个特定的header信息,就可以得知此stream需要请求的service、以及其method,那么接下来只需要从上述提到的map中找到service,然后找到此method,直接代理调用即可。执行结果在Encoder之后发送给Client。(参见:NettyServerHandler)

 

    因为是map存储,所以我们需要在定义.proto文件时,尽可能的指定package信息,以避免因为service过多导致名称可能重复的问题。

 

    2、Client端

    我们使用ManagedChannelBuilder来创建客户端channel,ManagedChannelBuilder使用了provider机制,具体是创建了哪种channel有provider决定,可以参看META-INF下同类名的文件中的注册信息。当前Channel有2种:NettyChannelBuilder与OkHttpChannelBuilder。本人的当前版本中为NettyChannelBuilder;我们可以直接使用NettyChannelBuilder来构建channel。如下描述则针对NettyChannelBuilder:

    配置参数与NettyServerBuilder基本类似,再次不再赘言。默认情况下,Client端默认的eventLoopGroup线程池也是static的,全局共享的,默认线程个数为coreSize * 2。合理的线程池个数可以提高客户端的吞吐能力。

 

    ManagedChannel是客户端最核心的类,它表示逻辑上的一个channel;底层持有一个物理的transport(TCP通道,参见NettyClientTransport),并负责维护此transport的活性;即在RPC调用的任何时机,如果检测到底层transport处于关闭状态(terminated),将会尝试重建transport。(参见TransportSet.obtainActiveTransport())

    通常情况下,我们不需要在RPC调用结束后就关闭Channel,Channel可以被一直重用,直到Client不再需要请求位置或者Channel无法真的异常中断而无法继续使用。当然,为了提高Client端application的整体并发能力,我们可以使用连接池模式,即创建多个ManagedChannel,然后使用轮训、随机等算法,在每次RPC请求时选择一个Channel即可。(备注,连接池特性,目前GRPC尚未提供,需要额外的开发)

 

    每个Service客户端,都生成了2种stub:BlockingStub和FutureStub;这两个Stub内部调用过程几乎一样,唯一不同的是BlockingStub的方法直接返回Response Model,而FutureStub返回一个Future对象。BlockingStub内部也是基于Future机制,只是封装了阻塞等待的过程:

Java代码  技术分享图片
  1. try   
  2.         //也是基于Future  
  3.       ListenableFuture<RespT> responseFuture = futureUnaryCall(call, param);  
  4.       //阻塞过程  
  5.       while (!responseFuture.isDone())   
  6.         try   
  7.           executor.waitAndDrain();  
  8.          catch (InterruptedException e)   
  9.           Thread.currentThread().interrupt();  
  10.           throw Status.CANCELLED.withCause(e).asRuntimeException();  
  11.           
  12.         
  13.       return getUnchecked(responseFuture);  
  14.      catch (Throwable t)   
  15.       call.cancel();  
  16.       throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);  
  17.   

 

    创建一个Stub的成本是非常低的,我们可以在每次请求时都通过channel创建新的stub,这并不会带来任何问题(只不过是创建了大量对象);其实更好的方式是,我们应该使用一个Stub发送多次请求,即Stub也是可以重用的;直到Stub上的状态异常而无法使用。最常见的异常,就是“io.grpc.StatusRuntimeException: DEADLINE_EXCEEDED”,即表示DEADLINE时间过期,我们可以为每个Stub配置deadline时间,那么如果此stub被使用的时长超过此值(不是空闲的时间),将不能再发送请求,此时我们应该创建新的Stub。很多人想尽办法来使用“withDeadlineAfter”方法来实现一些奇怪的事情,此参数的主要目的就是表明:此stub只能被使用X时长,此后将不能再进行请求,应该被释放。所以,它并不能实现类似于“keepAlive”的语义,即使我们需要keepAlive,也应该在Channel级别,而不是在一个Stub上。

 

    如果你使用了连接池,那么其实连接池不应该关注DEADLINE的错误,只要Channel本身没有terminated即可;就把这个问题交给调用者处理。如果你也对Stub使用了对象池,那么你就可能需要关注这个情况了,你不应该向调用者返回一个“DEADLINE”的stub,或者如果调用者发现了DEADLINE,你的对象池应该能够移除它。

 

    1)实例化ManagedChannel,此channel可以被任意多个Stub实例引用;如上文说述,我们可以通过创建Channel池,来提高application整体的吞吐能力。此Channel实例,不应该被shutdown,直到Client端停止服务;在任何时候,特别是创建Stub时,我们应该判定Channel的状态。

Java代码  技术分享图片
  1. synchronized (this)   
  2.     if (channel.isShutdown() || channel.isTerminated())   
  3.         channel = ManagedChannelBuilder.forAddress(poolConfig.host, poolConfig.port).usePlaintext(true).build();  
  4.       
  5.     //new Stub  
  6.   
  7.   
  8. //或者  
  9. ManagedChannel channel = (ManagedChannel)client.getChannel();  
  10. if(channel.isShutdown() || channel.isTerminated())   
  11.     client = createBlockStub();  
  12.   
  13. client.sayHello(...)  

 

    因为Channel是可以多路复用,所以我们用Pool机制(比如commons-pool)也可以实现连接池,只是这种池并非完全符合GRPC/HTTP2的设计语义,因为GRPC允许一个Channel上连续发送对个Requests(然后一次性接收多个Responses),而不是“交互式”的Request-Response模式,当然这么使用并不会有任何问题。

 

    2)对于批量调用的场景,我们可以使用FutureStub,对于普通的业务类型RPC,我们应该使用BlockingStub。

    3)每个RPC方法的调用,比如sayHello,调用开始后,将会为每个调用请求创建一个ClientCall实例,其内部封装了调用的方法、配置选项(headers)等。此后将会创建Stream对象,每个Stream都持有唯一的streamId,它是Transport用于分拣Response的凭证。最终调用的所有参数都会被封装在Stream中。

    4)检测DEADLINE,是否已经过期,如果过期,将使用FailingClientStream对象来模拟整个RPC过程,当然请求不会通过通道发出,直接经过异常流处理过程。

    5)然后获取transport,如果此时检测到transport已经中断,则重建transport。(自动重练机制,ClientCallImpl.start()方法)

    6)发送请求参数,即我们Request实例。一次RPC调用,数据是分多次发送,但是ClientCall在创建时已经绑定到了指定的线程上,所以数据发送总是通过一个线程进行(不会乱序)。

    7)将ClientCall实例置为halfClose,即半关闭,并不是将底层Channel或者Transport半关闭,只是逻辑上限定此ClientCall实例上将不能继续发送任何stream信息,而是等待Response。

    8)Netty底层IO将会对reponse数据流进行解包(Http2ConnectionDecoder),并根据streamId分拣Response,同时唤醒响应的ClientCalls阻塞。(参见ClientCalls,GrpcFuture)

    9)如果是BlockingStub,则请求返回,如果响应中包含应用异常,则封装后抛出;如果是网络异常,则可能触发Channel重建、Stream重置等。

 

 

    到此为止,已经把GRPC的基本原理描述完毕,此后如果有其他问题,则继续补充

grpc:使用golang开发grpc服务端和client

1,关于grpc-gogolang能够能够做grpc的服务端和client。官网的文档:http://www.grpc.io/docs/quickstart/go.htmlhttps://github.com/grpc/grpc-go和之前写的java的grpcclient调用同样。也须要使用protobuf的配置文件。可是golang以下的类库很的简单。并且golang... 查看详情

深入浅出掌握grpc通信框架(代码片段)

1.背景Alluxio底层使用到了Grpc作为底层通讯框架,为了弄清楚Alluxio服务端的线程模型,必然需要对Grpc代码有所掌握。本文先介绍Grpc底层HTTP2的知识,通过一个GRPC项目,深入GRPC源码,探索GRPC的线程模型。2.Grpc简介GRPC是Google推出... 查看详情

Dialogflow:抛出新错误(`@grpc/grpc-js 仅适用于节点 $supportedNodeVersions`)

】Dialogflow:抛出新错误(`@grpc/grpc-js仅适用于节点$supportedNodeVersions`)【英文标题】:Dialogflow:thrownewError(`@grpc/grpc-jsonlyworksonNode$supportedNodeVersions`)Dialogflow:抛出新错误(`@grpc/grpc-js仅适用于节点$supportedNodeVersions`)【发布时间】... 查看详情

grpc入门---1grpc简介

grpc自己介绍自己,重点突出高性能gRPCisamodern,opensource,high-performanceremoteprocedurecall(RPC)frameworkthatcanrunanywhere如果项目是用go写的,grpc也是一个不错的选择,使用java的对这个grpc的诟病很大,grpc很多插件没有1.grpc的接口设计  对于... 查看详情

grpc:使用golang开发grpc服务端和客户端

1,关于grpc-gogolang可以可以做grpc的服务端和客户端。官网的文档:http://www.grpc.io/docs/quickstart/go.htmlhttps://github.com/grpc/grpc-go和之前写的java的grpc客户端调用相同。也需要使用protobuf的配置文件。但是golang下面的类库非常的简单,而... 查看详情

gRPC - 公开公共 API

】gRPC-公开公共API【英文标题】:gRPC-ExposingPublicAPIs【发布时间】:2015-04-3007:28:12【问题描述】:2月26日,谷歌宣布gRPC:http://googledevelopers.blogspot.com.br/2015/02/introducing-grpc-new-open-source-http2.html在那篇文章中,他们说:“在Google内部... 查看详情

grpc如何便捷的调试grpc程序(代码片段)

前言gRPC是一款广泛应用的rpc框架,因为基于C/S架构,服务启动之后,需要编写对应的客户端才能调用,调试起来相对麻烦一些,这里主要介绍一下如何通过swagger-ui来调试grpc服务。grpc-swaggergRPC-swagger是基于gRPC... 查看详情

grpc如何便捷的调试grpc程序(代码片段)

前言gRPC是一款广泛应用的rpc框架,因为基于C/S架构,服务启动之后,需要编写对应的客户端才能调用,调试起来相对麻烦一些,这里主要介绍一下如何通过swagger-ui来调试grpc服务。grpc-swaggergRPC-swagger是基于gRPC... 查看详情

未解析的外部符号 - GRPC

】未解析的外部符号-GRPC【英文标题】:unresolvedexternalsymbol-GRPC【发布时间】:2019-09-2319:56:48【问题描述】:我使用protoc编译器编译了c++grpc文件,所以我认为引用不应该有任何问题。我添加了"grpc\\include"、"grpc\\src"和"grpc\\third_part... 查看详情

grpc负载均衡

...负载分布到多个服务器来提高应用的性能和可靠性。关于GRPC的负载均衡,我们选择NGINX来进行反向代理。NGINX在1.13.9版本已经开始支持GRPC代理。有了对GRPC的支持,NGINX就可以代理GRPCTCP连接,还可以终止、检查和跟踪GRPC的方法调... 查看详情

gRPC 和 Beta gRPC 类有啥区别?

】gRPC和BetagRPC类有啥区别?【英文标题】:What\'sthedifferencebetweengRPCandBetagRPCclasses?gRPC和BetagRPC类有什么区别?【发布时间】:2017-03-0712:21:58【问题描述】:我有以下proto文件,它将生成一个_pb2.py文件以在python中使用。syntax="proto3";... 查看详情

cmake方式编译grpc

首先,下载grpc源代码到本地:gitclonehttps://github.com/grpc/grpc.git如果只想下载指定版本的,如以版本“1.27.3”为例,可改成如下语句:gitclone-bv1.27.3https://github.com/grpc/grpc.git上列操作成功完成后,grpc源码的第三方依赖目录third_party实... 查看详情

生成 gRPC 服务类失败

】生成gRPC服务类失败【英文标题】:FailedtogenerategRPCserviceclasses【发布时间】:2017-08-0123:54:45【问题描述】:我正在尝试关注这个tutorial。我一直在尝试生成.grpc文件(服务类),但我能够生成消息类。当我跑步时protoc-I../proto--grp... 查看详情

grpc源码分析之域名解析

环境:  win7_x64,VS2015、grpc_1.3.1场景:  在客户端中使用grpc连接服务器,在多次输入非法的地址后,再次输入正确的地址连出现连接超时的现象。侯捷先生说过“源码面前,了无秘密”,所以开始分析grpc源码使用GRPC进行连... 查看详情

Grpc 无法解析符号 GreeterGrpc

】Grpc无法解析符号GreeterGrpc【英文标题】:GrpccannotresolvesymbolGreeterGrpc【发布时间】:2017-11-0520:45:08【问题描述】:我正在点击链接https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/helloworld来尝试让grpc正常工作。... 查看详情

3.微服务--grpc(代码片段)

1.gRPC入门1.1gRPC简介gRPC由google开发,是一款语言中立、平台中立、开源的远程过程调用系统gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用1.2gRPC与Protobuf介绍微服务架构中,... 查看详情

centos7下部署grpc(代码片段)

 gRPC是一个高性能、开源和通用的RPC框架,面向移动和HTTP/2设计。目前提供C、Java和Go语言版本,分别是:grpc,grpc-java,grpc-go.其中C版本支持C,C++,Node.js,Python,Ruby,Objective-C,PHP和C#。gRPC基于HTTP/2标准设计,带来诸如双向流、流控、... 查看详情

在grpc中添加记录中间(代码片段)

我试图在grpc服务器上添加一些日志中间件,我按照他们github上的简单例子来做。https:/github.comgrpc-ecosystemgo-grpc-中间件blobmasterlogginglogrusexamples_test.go。我把服务器选项设置成这样。var(logrusLogger*logrus.LoggercustomFuncgrpc_logrus.CodeToLevel)f... 查看详情