有一些服务A通过 GRpc(100+ 请求/秒)调用服务(10 个副本),java 生成存根。我们没有负载均衡器,但我很好奇这两种情况下的最佳实践是什么。
客户端是否应该在每次调用服务时构建通道A,还是应该创建一次 ManagedChannel 直到应用程序关闭?
如果我为每个请求创建一个,则调用将沿 10 个副本分发,但如果我仅在应用程序启动时创建,则所有调用都会转到同一个服务A副本。
另一方面,如果我在每次调用上创建,是否会打开数千个连接,直到它们空闲(默认为 30 分钟)?
ManagedChannel managedChannel = ManagedChannelBuilder
.forAddress(host, port)
.usePlaintext()
.build()
ServiceA.newBlockingStub(managedChannel)).fooBar(...)
Run Code Online (Sandbox Code Playgroud) 代码模型看起来像
Iterator iterator = grpc.invokeSomeRequest(requestData) //returns iterator
while(iterator.hasNext()){
//do some code.
}
Run Code Online (Sandbox Code Playgroud)
有时,错误会发生在iterator.hasNext()堆栈跟踪中:
UNAVAILABLE: io exception
io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
at io.grpc.Status.asRuntimeException(Status.java:533)
Run Code Online (Sandbox Code Playgroud)
grpc的版本是1.21.0
我发现这个问题最有可能出现在 grpc 上。我可能是错的。解决这个问题的最佳方法是什么?
第一次调用通常会成功,但随后我会收到如下消息:
io.grpc.StatusRuntimeException:DEADLINE_EXCEEDED:超出截止日期后开始 ClientCall:从现在开始-175.597476157s
为什么秒数是负数?我如何解决它?
我的 grpc 配置:
public class MyAppLibGrpcSenderConfig {
@Value("${grpc.client.host:localhost}")
private String host;
@Value("${grpc.client.port:9090}")
private int port;
@Value("${grpc.client.negotiationType:PLAINTEXT}")
private String negotiationType;
@Value("${grpc.client.deadline:300000}")
private long deadline;
@Autowired
private Tracer tracer;
@Bean
public ManagedChannel managedChannel() {
ManagedChannelBuilder<?> builder = ManagedChannelBuilder.forAddress(host, port);
if ("PLAINTEXT".equals(negotiationType)) {
builder.usePlaintext();
}
return builder.build();
}
@Bean
public TracingClientInterceptor tracingClientInterceptor(Tracer tracer) {
return TracingClientInterceptor
.newBuilder()
.withTracer(this.tracer)
.build();
}
@Bean
public MyAppSenderServiceGrpc.MyAppSenderServiceBlockingStub myAppSenderServiceBlockingStub(
TracingClientInterceptor tracingClientInterceptor,
ManagedChannel managedChannel) {
return MyAppSenderServiceGrpc
.newBlockingStub(tracingClientInterceptor.intercept(managedChannel))
.withDeadlineAfter(deadline, TimeUnit.MILLISECONDS);
}
@Bean
public MyAppCodeLoaderServiceGrpc.MyAppCodeLoaderServiceBlockingStub myAppCodeLoaderServiceBlockingStub( …Run Code Online (Sandbox Code Playgroud) javax从包切换到包后,我们正在使用 Jakarta 模块jakarta。当我使用 grpc-java 生成器时,生成的类包含:
@javax.annotation.Generated(
value = "by gRPC proto compiler (version 1.35.0)",
comments = "Source: echo.proto")
Run Code Online (Sandbox Code Playgroud)
这在我的项目中无法编译。我无法添加对javax包的依赖项,因为库是相同的:
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
仅版本不同(因此不能同时位于类路径上)。
有没有办法切换到jakarta.annotation.Generated或从生成的源中完全删除注释?
TL; DR
grpc-java是否ManagedChannel具有隐式连接池,或者ManagedChannel实例池由用户负责?
因此,我将Java grpc 1.1.2与协议3.2.0一起使用。在我看来,grpc为客户端提供的连接池没有隐式支持(到目前为止)。但是,似乎在grpc中连接的抽象(即ManagedChannel对象确实适用于多个TCP连接)。那是对的吗?如果是这样,ManagedChannel连接池是否附带了它?如果是这样的话,考虑到通道是线程安全的,我可能不必担心连接池,并且我可以ManagedChannel在整个客户端中使用单个实例。但是,如果需要,我可能确实也必须池化这些通道对象以提高吞吐量。是否有这样的实现(通道池)可以在grpc本身中为我实现?
当我们创建一个 managedChannelBuilder 并使用它来调用 grpc-java 服务调用时,我们可以用它服务多少个客户端?这个频道不是在个别服务呼叫后关闭吗?假设我有一个 REST 接口,它接受来自浏览器和这些 REST 服务方法中的 REST 调用,我正在对独立的 grpc 服务器进行 grpc 客户端调用。此外,我可以同时期待 [4000-5000] 范围内的客户端连接。我如何能很好地利用这个 managedChannelBuilder。我只需要一个吗?还是我需要汇集多个频道建设者?
我无法找到此错误的来源.我使用protobuf实现了一个简单的服务:
syntax = "proto3";
package tourism;
service RemoteService {
rpc Login(LoginUserDTO) returns (Response) {}
}
message AgencyDTO{
int32 id=1;
string name=2;
string email=3;
string password=4;
}
message LoginUserDTO{
string password=1;
string email=2;
}
message SearchAttractionsDTO{
string name=1;
int32 start_hour=2;
int32 start_minute=3;
int32 stop_hour=4;
int32 stop_minute=5;
AgencyDTO loggedUser=6;
}
message AttractionDTO{
int32 id=1;
string name=2;
string agency=3;
int32 hour=4;
int32 minute=5;
int32 seats=6;
int32 price=7;
}
message ReservationDTO{
int32 id=1;
string first_name=2;
string last_name=3;
string phone=4;
int32 seats=5;
AttractionDTO attraction=6;
AgencyDTO …Run Code Online (Sandbox Code Playgroud) 使用Grpc双向流,当我尝试运行grpc时,低于错误
Connection Error
io.netty.handler.codec.http2.Http2Exception: HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: at io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:82)
at io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:322)
at io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:263)
at io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:445)
at io.netty.handler.codec.ByteToMessageDecoder.decodeLast(ByteToMessageDecoder.java:382)
at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:286)
at io.netty.handler.codec.http2.Http2ConnectionHandler.channelInactive(Http2ConnectionHandler.java:421)
at io.grpc.netty.NettyServerHandler.channelInactive(NettyServerHandler.java:227)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelInactiveNow(ChannelHandlerInvokerUtil.java:56)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelInactive(DefaultChannelHandlerInvoker.java:92)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:135)
at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:928)
at io.netty.channel.AbstractChannel$AbstractUnsafe$7.run(AbstractChannel.java:674)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:339)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:356)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
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:748)
Run Code Online (Sandbox Code Playgroud)
可能是什么问题?
我正在寻找一种如何使用gRPC实现文件下载功能的方法,但我在文档中找不到这是如何完成的.
这样做的最佳方式是什么?我想拥有一个保存文件的gRPC服务器和一个gRPC客户端来请求来自gRPC的东西.
我查看了Java中的示例,但无法找到如何执行此操作的方法.我今天刚开始阅读有关gRPC的内容.
我正在编写一个 grpc 服务并在 Kubernetes ( https://github.com/grpc-ecosystem/grpc-health-probe )上使用 gRPC 健康检查。在我的服务器中,我添加了不同的端点实现(一个用于活动,另一个用于准备)。我想知道这个探针实用程序二进制文件如何区分活动检查与准备检查?在 yaml 中应该有一些其他的方式来定义它,而不仅仅是 ["bin/grpc_health_probe", "-addr=:8801"]
server = ServerBuilder.forPort(port)
.addService(new GrpcModuleHealthCheck())
.addService(new GrpcModuleReadinessCheck())
.addService(ProtoReflectionService.newInstance())
.build.start
Run Code Online (Sandbox Code Playgroud)
在 kubernetes 部署 yaml 中,我使用以下配置
livenessProbe:
failureThreshold: 3
exec:
command: ["bin/grpc_health_probe", "-addr=:8801"]
initialDelaySeconds: 240
periodSeconds: 20
successThreshold: 1
timeoutSeconds: 15
readinessProbe:
failureThreshold: 3
exec:
command: ["bin/grpc_health_probe", "-addr=:8801"]
initialDelaySeconds: 20
periodSeconds: 20
successThreshold: 1
timeoutSeconds: 15
Run Code Online (Sandbox Code Playgroud)
我刚刚测试并发现“GrpcModuleReadinessCheck”(我最后添加的健康类)实现在我刚刚执行我的 kubernetes pod 时生效
kubectl exec -it <MY_POD_NAME> -- /bin/bash
bash-4.4$ ./grpc_health_probe -addr=localhost:8801
status: SERVING
Run Code Online (Sandbox Code Playgroud)