gRPC Python thread_pool与max_concurrent_rpcs

Dav*_*ian 4 python concurrent.futures grpc

启动Python时grpc.server,线程池maximum_concurrent_rpcsmax_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,
)
Run Code Online (Sandbox Code Playgroud)

Att*_*123 5

如果您的服务器已经同时处理了maximum_concurrent_rpcs多个请求,但又收到另一个请求,则该请求将立即被拒绝。

如果ThreadPoolExecutor max_workers小于,maximum_concurrent_rpcs则在所有线程忙于处理请求之后,下一个请求将排队,并在线程完成其处理后进行处理。

我有同样的问题。为了回答这个问题,我调试了会发生什么maximum_concurrent_rpcs。调试进py36/lib/python3.6/site-packages/grpc/_server.py了我的virtualenv。搜索concurrency_exceeded。最重要的是,如果服务器已经在处理中maximum_concurrent_rpcs并且另一个请求到达,它将被拒绝:

# ...
elif concurrency_exceeded:
    return _reject_rpc(rpc_event, cygrpc.StatusCode.resource_exhausted,
                        b'Concurrent RPC limit exceeded!'), None
# ...
Run Code Online (Sandbox Code Playgroud)

我使用gRPCPython快速入门示例进行了尝试:

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)
# ...
Run Code Online (Sandbox Code Playgroud)

serve()方法:

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), maximum_concurrent_rpcs=2)
    # ...
Run Code Online (Sandbox Code Playgroud)

然后,我打开了3个终端,并手动执行了其中的客户端(使用以下命令即可完成python greeter_client.py

正如预期的那样,第2个客户端,请求处理立即开始(可以在服务器的输出中看到),因为有大量的可用线程,但第三客户得到立即拒绝(如预期)用StatusCode.RESOURCE_EXHAUSTEDConcurrent RPC limit exceeded!

现在测试在没有足够的线程分配给ThreadPoolExecutor我时将其修改max_workers为1的情况:

server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=2)
Run Code Online (Sandbox Code Playgroud)

我和之前大致相同的时间再次运行了3个客户。

结果是第一个立即送达。第二个需要等待10秒(而第一个需要送达),然后再送达。第三个立即被拒绝。