当前位置: 首页 > 知识库问答 >
问题:

用于长寿命流的Java gRPC服务器有效实现

陶树
2023-03-14

我想了解gRPC框架的一部分,用于长寿命流的资源管理。假设我们有无限的稀有事件源(每秒一次左右),我们希望通过grpc流将这些事件流到客户端。这些事件是由服务器上的单个应用程序线程生成的。

我看到了两种可能的流式事件实现:

  1. 在rpc调用中旋转调用线程,并通过(阻塞)队列与源进行通信

选项一看起来很简单,但线程数有点高——对于稀疏流,每个客户端一个线程似乎是一种过度使用。每个线程都会占用一些堆,等等。

第二种选择看起来更节约资源。然而,我在网上找不到任何支持这种方法的材料。我不确定gRPC服务器是否会意外关闭ServerCall或Context,导致流突然关闭。或者可能还有其他一些我不知道的副作用。

所以我的问题是:实现长寿命流的推荐方法是什么?有没有其他可能的方法来实现所描述的问题。选项2是合法的还是应该坚持1客户端1线程的方法?

我试着用选项二创建一个原型,它似乎正在工作。但我还是想得到答案。

共有1个答案

龚俭
2023-03-14

从gRPC的角度来看,这两种方法都很好。在方便的时候,你可以自由地使用一个客户端、一个线程的方法。对于流式传输的情况,通常最好避免在调用线程中旋转,但可以使用第二个线程来发送;这很正常。另一方面,将StreamObservers传递给单个线程进行管理具有资源优势,也是一种很好的方法。

当事件生成速度快于发送速度时,您应该考虑如何响应缓慢的客户端(即流控制)。

您需要将提供的StreamObserver转换为ServerCallStreamObserver,以访问其他API。它提供了setOnReadyHandler(Runnable)isReady()来检测慢速客户端。gRPC Java允许您调用onNext(…) 即使未准备好,但这样做会缓冲。

就绪处理程序是一个回调,它使用与调用者线程相同的线程,所以如果您在调用者线程中旋转,您将无法接收回调。这就是为什么对于流式传输,最好避免在调用者线程中旋转。

使用专用发送线程的优点是队列清晰,生产者和消费者之间分离。您可以选择队列大小,并决定当队列已满时该做什么。在一个线程中直接与Stream观察者交互会占用更少的资源。这两个选项的复杂性各不相同。“正确”的方法选择基于规模、资源考虑、服务的细节和偏好。

 类似资料:
  • 我正在通过以下示例寻找一个用于服务器端流的客户端侦听器示例-https://grpc.io/docs/languages/java/basics/ 我已经按照文档-https://github.com/grpc/grpc/blob/master/doc/keepalive.md 所有的例子都表明,当向服务器发出请求时,服务器将作为异步或一元模型响应,或者客户端可以与新请求聊天。每次请求都必须发送到

  • 问题内容: 我目前正在尝试诊断应用程序中的缓慢内存泄漏。到目前为止,我掌握的事实如下。 我有4天运行该应用程序的堆转储。 该堆转储包含约800个WeakReference对象,这些对象指向保留40mb内存的对象(所有对象都是同一类型,出于这个问题的目的,我将其称为Foo)。 Eclipse内存分析工具显示,这些WeakReferences引用的每个Foo对象均未被其他任何对象引用。我的期望是,这应

  • 使用Chrome访问您的https网站时,您可能会收到以下错误 NET::ERR\u CERT\u VALIDITY\u过长 服务器证书的有效期太长 如何允许请求在chrome中通过?

  • 根据PostgreSQL文档,准备好的语句绑定到数据库会话/连接: PREPARE创建一个prepared语句。准备好的语句是可用于优化性能的服务器端对象。执行PREPARE语句时,将解析、分析和重写指定的语句。当随后发出EXECUTE命令时,计划并执行准备好的语句。 PostgreSQL没有共享的查询计划缓存,但它有一个可选的查询计划缓存,用于准备好的语句。这意味着开发人员可以选择使用带有或不带

  • 我已经通过Firebase使用他们的API成功创建了一个动态链接,如下所示:https://firebase.google.com/docs/dynamic-links/rest#creating-a-short-dynamic-link.我想知道这些“动态生成”动态链接的寿命是多少?