我实现了无限流响应,就像使用gRPC架构的pub / sub模式一样。
有一个端点可以打开响应流并将其保留到客户端丢弃。为此,我存储了一个键值哈希,其中键是gRPC上下文,值是我用来轮询发送消息的队列。
我的端点代码如下:
def StreamTrades(self, request, context):
self.feeds[context] = queue.Queue()
callback_queue = queue.Queue()
def remove_feed():
if self.feeds.get(context) is not None:
del self.feeds[context]
def stop_stream():
remove_feed()
def raise_stop_stream_exception():
raise StopStream('stopping stream')
callback_queue.put(raise_stop_stream_exception)
context.add_callback(stop_stream)
def output_generator():
while True:
try:
try:
callback = callback_queue.get(False)
callback()
except queue.Empty:
pass
if self.feeds.get(context) is not None:
trade = self.feeds[context].get()
if isinstance(trade, trades_pb2.Trade):
yield trade
else:
raise StopStream('stopping stream')
except IndexError:
pass
except StopStream:
return
return output_generator()
此代码适用于订阅和发布客户端更改。但是有一个与取消订阅有关的问题。检测客户端丢弃的好方法是什么?使用Context.add_callback(callBack)似乎不起作用,因为只有在服务器完成并关闭流时才会调用回调。当客户端不再存在时,生成器不会引发任何类型的状态。我在Java中看到,当在streamObserver中调用onNext并且没有客户端抛出Status.CANCELLED的StatusRuntimeException时,它允许对我来说已经足够的延迟取消订阅。
有没有办法检测客户端在响应流中丢弃连接?
答案 0 :(得分:3)
当客户端断开连接时,应调用您向ServicerContext.add_callback
注册的回调;没有被调用表明你患有this bug。 不的情况是"回调仅在服务器完成并关闭流时被调用"。