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

用于长寿命流的Java gRPC服务器有效实现,java,grpc,grpc-java,Java,Grpc,Grpc Java,我想了解gRPC框架的一部分,用于长期流的资源管理。 假设我们有无限的稀有事件源(每秒一次左右),我们希望通过grpc流将这些事件流到客户端。 事件由服务器上的单个应用程序线程生成 我看到两种可能的流式事件实现: 在rpc调用中旋转调用方线程,并通过(阻塞)队列与源进行通信 向事件生成线程公开StreamObserver,并从中填充所有客户端流 选项一看起来很简单,但线程数量有点过多——对于稀疏流,每个客户机一个线程似乎有点过分了。每个线程占用一些堆调度程序,以此类推 选项二看起来对资源更为友好

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

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

  • 在rpc调用中旋转调用方线程,并通过(阻塞)队列与源进行通信
  • 向事件生成线程公开StreamObserver,并从中填充所有客户端流
  • 选项一看起来很简单,但线程数量有点过多——对于稀疏流,每个客户机一个线程似乎有点过分了。每个线程占用一些堆调度程序,以此类推

    选项二看起来对资源更为友好。然而,我在互联网上找不到任何支持这种方法的材料。我不确定gRPC服务器是否会意外地关闭ServerCall或上下文,从而导致流突然关闭。或者可能还有一些我不知道的副作用

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

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

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

    您应该考虑如何响应慢客户机,当事件生成的速度比它们发送的速度快(即流量控制)时,

    您需要将提供的
    StreamObserver
    转换为
    ServerCallStreamObserver
    ,以访问其他API。它提供和用于检测慢速客户端。GRPCJava允许您调用
    onNext(…)
    ,即使在未准备就绪的情况下,但这样做会导致缓冲区失效

    on ready处理程序是一个回调,它使用与调用线程相同的线程,因此如果在调用线程中旋转,您将无法接收该回调。这就是为什么对于流式处理,通常最好避免在调用线程中旋转


    使用专用的发送线程具有以下优点:队列清晰,生产者和消费者分离。您可以选择队列大小,并决定当该队列已满时要执行的操作。在一个线程中直接与
    StreamObserver
    s交互可以减少资源使用。两种选择的复杂性各不相同。“正确”的方法选择是基于规模、资源考虑、服务细节和您的偏好。

    谢谢您,Eric,快速详细的回复!事实上,单响应线程看起来更加资源友好。我将研究有关流控制的ServerCallStreamObserver API。虽然对我来说,更新所有客户端而不删除任何消息是非常重要的。也许我应该调查一下比迪的沟通。关于缓冲的问题-有没有控制缓冲区大小的方法?缓冲区将不受限制地增长,只有isReady()提示告诉您它的大小正在增长。是允许配置isReady()阈值的功能请求。