gRPC Python thread_pool 对比 max_concurrent_rpcs
gRPC Python thread_pool vs max_concurrent_rpcs
启动Pythongrpc.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
, Concurrent RPC limit exceeded!
.
现在测试当没有足够的线程分配给 ThreadPoolExecutor
时会发生什么,我将 max_workers
修改为 1:
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=2)
我 运行 我的 3 个客户大约在与以前相同的时间再次出现。
结果是第一个立即得到服务。第二个需要等待 10 秒(当第一个被送达时)然后它被送达。第三个直接被拒
启动Pythongrpc.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
, Concurrent RPC limit exceeded!
.
现在测试当没有足够的线程分配给 ThreadPoolExecutor
时会发生什么,我将 max_workers
修改为 1:
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=2)
我 运行 我的 3 个客户大约在与以前相同的时间再次出现。
结果是第一个立即得到服务。第二个需要等待 10 秒(当第一个被送达时)然后它被送达。第三个直接被拒