启动 Python grpc.server
时,maximum_concurrent_rpcs
和线程池中使用的 max_workers
有什么区别。如果我想要 maximum_concurrent_rpcs=1
,我是否仍应向线程池提供多个线程?
换句话说,我应该将 maximum_concurrent_rpcs
与我的 max_workers
相匹配,还是应该提供比最大并发 RPC 更多的工作人员?
server = grpc.server(
thread_pool=futures.ThreadPoolExecutor(max_workers=1),
maximum_concurrent_rpcs=1,
)
最佳答案
如果您的服务器已经同时处理了 maximum_concurrent_rpcs
个请求,并且又收到另一个请求,则该请求将立即被拒绝。
如果 ThreadPoolExecutor 的 max_workers
小于 maximum_concurrent_rpcs
那么在所有线程都忙于处理请求后,下一个请求将被排队,并在一个线程完成它的时候被处理处理。
我也有同样的疑问。为了回答这个问题,我调试了一下 maximum_concurrent_rpcs
会发生什么。调试转到了我的 virtualenv
中的 py36/lib/python3.6/site-packages/grpc/_server.py
。搜索 concurrency_exceeded
。底线是,如果服务器已经在处理 maximum_concurrent_rpcs
并且另一个请求到达,它将被拒绝:
# ...
elif concurrency_exceeded:
return _reject_rpc(rpc_event, cygrpc.StatusCode.resource_exhausted,
b'Concurrent RPC limit exceeded!'), None
# ...
我用 gRPC
Python 快速入门示例进行了尝试:
在 greeter_server.py
中,我修改了 SayHello()
方法:
# ...
def SayHello(self, request, context):
print("Request arrived, sleeping a bit...")
time.sleep(10)
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
# ...
和 serve()
方法:
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), maximum_concurrent_rpcs=2)
# ...
然后我打开 3 个终端并在其中手动执行客户端(尽可能快地使用 python greeter_client.py
:
正如预期的那样,对于前 2 个客户端,请求的处理立即开始(可以在服务器的输出中看到),因为有足够的线程可用,但是第 3 个客户端立即被拒绝(如预期的那样)StatusCode.RESOURCE_EXHAUSTED
,超出并发 RPC 限制!
。
现在要测试当没有足够的线程分配给 ThreadPoolExecutor
时会发生什么,我将 max_workers
修改为 1:
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=2)
我在与之前大致相同的时间再次运行我的 3 个客户端。
结果是第一个立即得到服务。第二个需要等待 10 秒(当第一个被送达时)然后它被送达。第三个立即被拒绝。
关于python - gRPC Python thread_pool 与 max_concurrent_rpcs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51089746/