「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
gRPC Metadata 是通过什么传输?
gRPC 的附加信息都会体现在 HEADERS 帧,数据在 DATA 帧上
调用 grpc.Dial 会真正的去连接服务端吗?
会,但是是异步连接的,连接状态为正在连接【当时状态为 Connecting】。但如果你设置了 grpc.WithBlock 选项,就会阻塞等待(等待握手成功)【完成状态为 Ready】。另外你需要注意,当未设置 grpc.WithBlock 时,ctx 超时控制对其无任何效果。
调用 ClientConn 不 Close 会导致泄露吗?
会,除非你的客户端不是常驻进程,那么在应用结束时会被动地回收资源。但如果是常驻进程,你又真的忘记执行 Close语句,会造成的泄露。如下图:
不控制超时调用的话,会出现什么问题?
短时间内不会出现问题,但是会不断积蓄泄露,积蓄到最后当然就是服务无法提供响应了。
客户端请求失败后会默认重试吗?
会不断地进行重试,直到上下文取消。而重试时间方面采用 backoff 算法作为的重连机制,默认的最大重试时间间隔是 120s。
为什么要用 HTTP/2 作为传输协议?
许多客户端要通过 HTTP 代理来访问网络,gRPC 全部用 HTTP/2 实现,等到代理开始支持 HTTP/2 就能透明转发 gRPC 的数据。不光如此,负责负载均衡、访问控制等等的反向代理都能无缝兼容 gRPC,比起自己设计 wire protocol 的 Thrift,这样做科学不少。
在 Kubernetes 中 gRPC 负载均衡有问题?
gRPC 的 RPC 协议是基于 HTTP/2 标准实现的,HTTP/2 的一大特性就是不需要像 HTTP/1.1 一样,每次发出请求都要重新建立一个新连接,而是会复用原有的连接。
所以这将导致 kube-proxy 只有在连接建立时才会做负载均衡,而在这之后的每一次 RPC 请求都会利用原本的连接,那么实际上后续的每一次的 RPC 请求都跑到了同一个地方。 注:使用 k8s service 做负载均衡的情况下
gRPC返回参数体
grpc.github.io/grpc/core/m… gRPC拥有自己的一套消息返回体格式,在发生异常的时候可以使用其中的枚举类型,不然就会出现推荐和大数据项目之间相互调用的时候报的UNKONW
2021-06-18 18:01:30.231 |feature-executor-92 |ERROR |com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl |- |2b5739c049cee4fb |getUserStatusCrossFeatureValue featureIds:[100082, 100083] error\
java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: UNKNOWN\
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)\
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1907)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl.getUserStatusCrossFeatureValue(BigDataFeatureServiceImpl.java:265)\
at com.xueqiu.snowflake.recommend.core.service.impl.AssemblyFeatureServiceImpl.lambda$prepareFeatures$115(AssemblyFeatureServiceImpl.java:225)\
at com.xueqiu.snowflake.recommend.core.service.impl.AssemblyFeatureServiceImpl$$Lambda$1337/1087217946.run(Unknown Source)\
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1618)\
at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:62)\
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\
at java.lang.Thread.run(Thread.java:745)\
Caused by: io.grpc.StatusRuntimeException: UNKNOWN\
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:235)\
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:216)\
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)\
at com.xueqiu.bigdata.label.proto.FeatureQueryServiceGrpc$FeatureQueryServiceBlockingStub.getFeatureCrossValue(FeatureQueryServiceGrpc.java:429)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl.lambda$null$329(BigDataFeatureServiceImpl.java:246)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl$$Lambda$1552/1915196135.run(Unknown Source)\
... 5 common frames omitted
可以在异常返回的时候使用Status,或者使用自定义的pb对象
@Override
public void timeoutHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
HelloReply resp = HelloReply.newBuilder().setMessage(fooService.createMsg(request.getName())).build();
try {
TimeUnit.SECONDS.sleep(20);
responseObserver.onNext(resp);
responseObserver.onCompleted();
} catch (Exception e) {
responseObserver.onError(Status.INTERNAL.withDescription(e.getMessage()).asException());
}
}
解决后调用接收到异常之后的效果
2021-06-18 20:33:12.203 |feature-executor-34 |ERROR |com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl |- |4a161bb19faf3ed6 |getUserStatusCrossFeatureValue featureIds:[100082, 100083], statusIds:[184235224, 184228201, 184220178], size:500 error\
java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: DATA_LOSS: 获取用户交叉特征数据错误,null\
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)\
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1907)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl.getUserStatusCrossFeatureValue(BigDataFeatureServiceImpl.java:265)\
at com.xueqiu.snowflake.recommend.core.service.impl.AssemblyFeatureServiceImpl.lambda$prepareFeatures$303(AssemblyFeatureServiceImpl.java:225)\
at com.xueqiu.snowflake.recommend.core.service.impl.AssemblyFeatureServiceImpl$$Lambda$1237/1840793554.run(Unknown Source)\
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1618)\
at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:62)\
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\
at java.lang.Thread.run(Thread.java:745)\
Caused by: io.grpc.StatusRuntimeException: DATA_LOSS: 获取用户交叉特征数据错误,null\
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:235)\
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:216)\
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)\
at com.xueqiu.bigdata.label.proto.FeatureQueryServiceGrpc$FeatureQueryServiceBlockingStub.getFeatureCrossValue(FeatureQueryServiceGrpc.java:429)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl.lambda$null$689(BigDataFeatureServiceImpl.java:246)\
at com.xueqiu.snowflake.recommend.core.feature.impl.BigDataFeatureServiceImpl$$Lambda$1247/1607196341.run(Unknown Source)\
... 5 common frames omitted\