假设我正在使用带有以下 .proto
的 gRPC 构建一个简单的聊天应用程序:
service Chat {
rpc SendChat(Message) returns (Void);
rpc SubscribeToChats(Void) returns (stream Message);
}
message Void {}
message Message {string text = 1;}
我经常看到用 Python 实现的服务程序(在示例中)是这样的:
class Servicer(ChatServicer):
def __init__(self):
self.messages = []
def SendChat(self, request, context):
self.messages.append(request.text)
return Void()
def SubscribeToChats(self, request, context):
while True:
if len(self.messages) > 0:
yield Message(text=self.messages.pop())
虽然这有效,但生成一个无限循环来不断检查每个连接的客户端的条件似乎效率很低。最好使用这样的方式,即在消息传入时立即触发发送,并且不需要在条件下进行任何持续轮询:
class Servicer(ChatServicer):
def __init__(self):
self.listeners = []
def SendChat(self, request, context):
for listener in self.listeners:
listener(Message(request.text))
return Void()
def SubscribeToChats(self, request, context, callback):
self.listeners.append(callback)
但是,我似乎找不到使用 gRPC 执行此类操作的方法。
我有以下问题:
提前致谢!
答案 0 :(得分:0)
我想出了一个有效的方法来做到这一点。关键是使用AsyncIO API。现在我的 SubscribeToChats
函数可以是一个异步生成器,这让事情变得更容易了。
现在我可以使用像 asyncio Queue 这样的东西,我的函数可以在 while 循环中等待它。类似这样:
class Servicer(ChatServicer):
def __init__(self):
self.queue = asyncio.Queue()
async def SendChat(self, request, context):
await self.queue.put(request.text)
return Void()
async def SubscribeToChats(self, request, context):
while True:
yield Message(text=await self.queue.get())