本文介绍了Java GRPC服务器对长寿命流的有效实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  1. 在RPC调用中调入调用者线程,并通过(阻塞)队列与源进行通信
  2. 向事件生成线程公开StreamWatch,并从那里填充所有客户端流。
选项一看起来很简单,但线程计数有点重-稀疏流的每个客户端一个线程似乎有点过头了。每个线程占用一些堆,占用调度程序,等等。

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

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

我尝试使用选项2创建一个原型,它似乎起作用了。但我仍然希望得到答案。

推荐答案

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

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

您需要将提供的StreamObserver转换为ServerCallStreamObserver以访问其他接口。提供检测慢客户端的setOnReadyHandler(Runnable)isReady()。GRPC Java允许您在尚未准备好的情况下调用onNext(...),但这样做将会缓冲。

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

使用专用发送线程的优点是队列清晰,生产者和消费者之间可以分离。您可以选择队列大小,并决定在该队列已满时执行什么操作。在一个线程中直接与StreamObserver交互会占用较少的资源。这两种选择的复杂程度各不相同。选择正确的方法取决于规模、资源考虑因素、服务细节和您的首选项。

这篇关于Java GRPC服务器对长寿命流的有效实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 04:29