问题描述
假设我需要使用python gRPC从客户端向服务器发送大量数据。我想在发送消息时继续其余的计算,而不是阻塞代码。有什么办法可以实现呢?
我将使用greeter_client.py中的修改后的代码通过示例来说明问题。
for i in range(5):
res=computation()
response = stub.SayHello(helloworld_pb2.HelloRequest(data=res))
我希望在发送上一次迭代的“ res”时继续进行下一次迭代的计算。为此,我尝试了“ async / await”,它看起来像这样
async with aio.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
for j in range(5):
res=computation()
response = await stub.SayHello(helloworld_pb2.HelloRequest(data=res))
但是运行时间实际上与没有异步/等待的版本相同。异步/等待不起作用。我想知道我的代码中是否有任何错误或其他方法?
解决方法
并发不同于并行。 AsyncIO允许多个协程在同一线程上运行,但实际上并非同时计算它们。如果您的代码段中给线程分配了诸如“ computation()”之类的CPU繁重的工作,则它不会将控制权归还给事件循环,因此在其他协程上不会有任何进展。
此外,在代码段中,RPC取决于“ computation()”的结果,这意味着将为每个RPC序列化工作。但是我们仍然可以通过使用asyncio.gather()
将它们移交给事件循环来从AsyncIO中获得一些并发性:
async with aio.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
async def one_hello():
res=computation()
response = await stub.SayHello(helloworld_pb2.HelloRequest(data=res))
await asyncio.gather(*(one_hello() for _ in range(5)))