【发布时间】:2020-12-16 15:20:03
【问题描述】:
今天我想开始为我用 Python 编写的程序实现 gRPC 客户端和服务器。我已按照此处找到的教程进行操作:https://grpc.io/docs/languages/python/quickstart/。
按照我的意思是我完全按照指示,按所写的方式输入每个命令。首先安装所有需求(在 conda 环境中),然后运行 greeter_server.py 和 greeter_client.py。从技术上讲,该程序可以工作,但客户端程序在我的系统上挂起大约 30-40 秒,然后以简单的问候语“收到问候客户:您好!”作为响应。
所以我决定尝试这里的快速入门教程的 Go 版本:https://grpc.io/docs/languages/go/quickstart/。再次完全按照书面说明进行操作,构建并启动 go 服务器和 go 客户端,客户端程序在不到一秒的时间内响应“2020/08/27 12:48:24 Greeting: Hello world”。
go 版本的行为完全符合我的预期。然而,Python 版本需要将近一分钟才能回复一条简单的消息。有人知道发生了什么吗?
提前致谢。
编辑 1) - 我将用我刚刚完成的一些测试来补充原始问题。对于原文中的缺失,我深表歉意。所以,我一直在不同的机器上进行测试。在我的 Ubuntu 20 机器桌面上,问题存在。我可以简单地弹出一个终端,创建一个新的 conda 环境(我使用 Python 3.8 进行这些测试)。我执行快速入门教程。 Python 版本没有按预期工作(说服我一切正常工作需要很长时间)。我在 Go 中执行了快速入门,一切都运行良好。
我在我的 2011 mac book air 上测试了本教程,启动了一个终端,创建了一个新的 conda 环境 (3.8),与Go 版本。
所以我想知道是否有任何 gRPC 专家会对为什么会发生这种情况提出建议。我已经重启了我的机器并再次测试,我的 Ubuntu linux 机器上仍然存在问题。
编辑 2) - 我刚刚在 Ubuntu 20 云虚拟机上进行了类似的测试,一切正常(Python 和 Go 版本之间没有区别)。我尝试了我在网上找到的一个单独的随机“echo”gRPC Python 教程(与 gRPC 快速入门教程无关),问题仍然存在于我的本地。所以我相信这个问题可以与我的环境隔离。我迷路了。
编辑 3) - 我通过调试器运行客户端代码并添加断点。
from __future__ import print_function
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('localhost:50051') as channel: # added break
stub = helloworld_pb2_grpc.GreeterStub(channel) # added break
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) # added break - HANGS ASSINING `response` OBJECT
print("Greeter client received: " + response.message) # added break
if __name__ == '__main__':
logging.basicConfig()
run()
它挂在 print 语句之前,在 with 块内。在我的 Mac 上,我设置了相同的断点,调试器立即将响应对象分配给内存并打印。在我的 Ubuntu 机器上,调试器挂起试图分配 response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) 变量。我注意到 Cython 的使用可能是一个线索。
如果我中断了 greeter_client.py 进程,我会得到以下跟踪:
File "greeter_client.py", line 37, in <module>
run()
File "greeter_client.py", line 31, in run
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
File "/home/james/.local/lib/python3.8/site-packages/grpc/_channel.py", line 824, in __call__
state, call, = self._blocking(request, timeout, metadata, credentials,
File "/home/james/.local/lib/python3.8/site-packages/grpc/_channel.py", line 813, in _blocking
event = call.next_event()
File "src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi", line 338, in grpc._cython.cygrpc.SegregatedCall.next_event
File "src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi", line 169, in grpc._cython.cygrpc._next_call_event
File "src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi", line 163, in grpc._cython.cygrpc._next_call_event
File "src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi", line 63, in grpc._cython.cygrpc._latent_event
File "src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi", line 42, in grpc._cython.cygrpc._next
KeyboardInterrupt
Edit 4) - 其中一位评论者提出了一个很好的建议来测试 python 客户端和 go 服务器组合(gRPC 允许零努力,go gRPC)。我执行了测试,Python 客户端的响应速度仍然很慢。 Go 客户端 - Go 服务器组合仍然很快。我相信这将其缩小到 Python 客户端的问题。谢谢@DazWilkin。为了完整起见,Go 客户端 - Python 服务器在
编辑 5) - 昨晚我完全重新安装了 Ubuntu 20.04 的最小版本。在新系统上,简单的 greeter_client.py 响应仍有大约 45 秒的延迟。 :(
【问题讨论】:
-
您是否尝试过在两个版本上运行分析器来详细比较它们的性能?
-
我没有尝试分析源。目前我假设有一个合理的解释和一些简单而明显的事情,我不明白为什么会发生这种情况。
-
这是一个奇怪的问题。您是否尝试过(在本地)使用带有 Go 服务器的 Python 客户端和带有 Python 服务器的 Go 客户端? gRPC 的一个优点是它可以工作,并且可能有助于消除问题。
-
谢谢@DazWilkin。我执行了您建议的测试和 Python 客户端 - Go 服务器。问题仍然存在。感谢您的建议。
-
您解决了吗?也许尝试使用 virtualenv 而不是 conda?也许尝试将
stub.SayHello和print(response.message)包装在while True中,可能还带有time.sleep(1)以消除启动时间?