我想了解 gRPC 框架的一部分,用于长期流的资源管理。
假设我们有无限的罕见(每秒一次左右)事件源,我们希望通过 grpc 流的方式将其流式传输到客户端。
这些事件由服务器上的单个应用程序线程生成。
我看到两种可能的流事件实现:
- 在 rpc 调用中旋转调用者线程并通过(阻塞)队列与源通信
- 将 StreamObserver 暴露给事件生成线程并从那里填充所有客户端流。
选项一看起来很简单,但线程数有点重 - 每个客户端一个线程用于稀疏流似乎有点大材小用。每个线程都需要一些堆占用调度程序等等。
选项二看起来更加资源友好。但是我在互联网上找不到任何材料来支持这种方法。我不确定 gRPC 服务器不会意外关闭 ServerCall 或 Context,从而导致流突然关闭。或者可能还有一些我不知道的其他副作用。
所以我的问题是:
实现长期流的推荐方法是什么?
是否有任何其他可能的方法来解决所描述的问题。
选项 2 是否合法,还是应该坚持使用 1 个客户端 1 个线程的方法?
我尝试用选项二创建一个原型,它似乎有效。
但我还是想得到答案。
从 gRPC 的角度来看,这两种方法都很好。如果方便的话,您可以自由地坚持使用 1 个客户端、1 个线程的方法。对于流传输情况,通常最好避免在调用者线程中旋转,但您可以使用第二个线程来发送;这很正常。另一方面,通过StreamObserver
使用单个线程进行管理具有资源优势,也是一个很好的方法。
当事件生成速度快于发送速度时,您应该考虑如何响应缓慢的客户端(即流量控制)。
您将需要投射提供的StreamObserver
to ServerCallStreamObserver
访问其他 API。它提供setOnReadyHandler(Runnable) https://grpc.github.io/grpc-java/javadoc/io/grpc/stub/CallStreamObserver.html#setOnReadyHandler-java.lang.Runnable- and isReady() https://grpc.github.io/grpc-java/javadoc/io/grpc/stub/CallStreamObserver.html#isReady--用于检测速度慢的客户端。 gRPC Java 允许您调用onNext(...)
即使没有准备好,但这样做会缓冲。
就绪处理程序是一个回调,它使用与调用者线程相同的线程,因此如果您在调用者线程中旋转,您将无法接收该回调。这就是为什么对于流式传输来说,通常最好避免在调用者线程中旋转。
使用专用的发送线程具有清晰的队列以及生产者和消费者之间分离的优点。您可以选择队列大小并决定队列已满时要执行的操作。直接与StreamObserver
一个线程中的 s 资源使用量较少。两个选项的复杂性各不相同。 “正确”的方法选择基于规模、资源考虑、服务的具体情况以及您的偏好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)