gRPC 服务器 pytest 错误: statusCode.UNKNOWN

huangapple go评论72阅读模式
英文:

gRPC server pytest error: statusCode.UNKNOWN

问题

我实现了一个小型服务器,并尝试使用pytest来验证它:

@pytest.mark.asyncio
async def test_poc_server():
    # 启动 PoC 服务器
    server = PoCGrpcServer(50051)
    await server.start()
    # 创建一个连接到服务器的客户端
    async with grpc.aio.insecure_channel('localhost:50051') as channel:
        stub = PoCStub(channel)
        response = await stub.Move(poc__pb2.MoveRequest(x=10.0, y=10.0))
    assert response.result() == poc__pb2.MoveResponse

但是测试在stub.Move()处失败,并显示以下错误:

> response = await stub.Move(poc__pb2.MoveRequest(x=10.0, y=10.0))

tests/test_grpc_server.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_AioCall of RPC that terminated with:
        status = Exception calling application: 
        details = "StatusCode.UNKNOWN"
        debu...peer  {created_time:"2023-06-15T14:38:59.0601+02:00", grpc_status:2, grpc_message:"Exception calling application: "}"
>

    def __await__(self) -> ResponseType:
        """等待正在进行的 RPC 请求完成。"""
        try:
            response = yield from self._call_response
        except asyncio.CancelledError:
            # 即使我们捕获了所有其他 CancelledError,仍然存在这种情况。如果应用程序在创建 Call 对象后立即取消,我们将观察到这个“CancelledError”。
            if not self.cancelled():
                self.cancel()
            raise
    
        # 注意(lidiz) 如果我们在任务中引发 RpcError,并且用户没有 'await' 它,AsyncIO 将记录 '任务异常未被检索到'。相反,如果我们将异常引发在这里,垃圾邮件就会停止。
        # 不幸的是,在 '__await__' 中只能有一个 'yield from'。所以,我们需要访问私有实例变量。
        if response is cygrpc.EOF:
            if self._cython_call.is_locally_cancelled():
                raise asyncio.CancelledError()
            else:
>               raise _create_rpc_error(self._cython_call._initial_metadata,
                                        self._cython_call._status)
E               grpc.aio._call.AioRpcError: <AioRpcError of RPC that terminated with:
E                       status = StatusCode.UNKNOWN
E                       details = "Exception calling application: "
E                       debug_error_string = "UNKNOWN:Error received from peer  {created_time:"2023-06-15T14:38:59.0601+02:00", grpc_status:2, grpc_message:"Exception calling application: "}"
E               >

../../../../Library/Caches/pypoetry/virtualenvs/pytaf-6R8xcXyw-py3.11/lib/python3.11/site-packages/grpc/aio/_call.py:290: AioRpcError

我认为这可能与服务器和客户端都在同一个 asyncio 运行器上运行有关,但我不太确定...
有趣的是,https://pypi.org/project/pytest-grpc/ 显示了相同的错误,但我不清楚修复方法是什么。

英文:

I implemented a small server and try with pytest to validate it:

@pytest.mark.asyncio
async def test_poc_server():
    # Start poc server
    server = PoCGrpcServer(50051)
    await server.start()
    # Create a client that connects to the server
    async with grpc.aio.insecure_channel('localhost:50051') as channel:
        stub = PoCStub(channel)
        response = await stub.Move(poc__pb2.MoveRequest(x=10.0, y=10.0))
    assert response.result() == poc__pb2.MoveResponse

And the test fails on the stub.Move() with the following error:


>           response = await stub.Move(poc__pb2.MoveRequest(x=10.0, y=10.0))

tests/test_grpc_server.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_AioCall of RPC that terminated with:
        status = Exception calling application: 
        details = "StatusCode.UNKNOWN"
        debu...peer  {created_time:"2023-06-15T14:38:59.0601+02:00", grpc_status:2, grpc_message:"Exception calling application: "}"
>

    def __await__(self) -> ResponseType:
        """Wait till the ongoing RPC request finishes."""
        try:
            response = yield from self._call_response
        except asyncio.CancelledError:
            # Even if we caught all other CancelledError, there is still
            # this corner case. If the application cancels immediately after
            # the Call object is created, we will observe this
            # `CancelledError`.
            if not self.cancelled():
                self.cancel()
            raise
    
        # NOTE(lidiz) If we raise RpcError in the task, and users doesn't
        # 'await' on it. AsyncIO will log 'Task exception was never retrieved'.
        # Instead, if we move the exception raising here, the spam stops.
        # Unfortunately, there can only be one 'yield from' in '__await__'. So,
        # we need to access the private instance variable.
        if response is cygrpc.EOF:
            if self._cython_call.is_locally_cancelled():
                raise asyncio.CancelledError()
            else:
>               raise _create_rpc_error(self._cython_call._initial_metadata,
                                        self._cython_call._status)
E               grpc.aio._call.AioRpcError: <AioRpcError of RPC that terminated with:
E                       status = StatusCode.UNKNOWN
E                       details = "Exception calling application: "
E                       debug_error_string = "UNKNOWN:Error received from peer  {created_time:"2023-06-15T14:38:59.0601+02:00", grpc_status:2, grpc_message:"Exception calling application: "}"
E               >

../../../../Library/Caches/pypoetry/virtualenvs/pytaf-6R8xcXyw-py3.11/lib/python3.11/site-packages/grpc/aio/_call.py:290: AioRpcError

I think it may have something to do with the server and client running both on the same asyncio runner but I'm not sure...
What is interesting is that https://pypi.org/project/pytest-grpc/ shows the same error but it is not clear for me what the fix would be.

答案1

得分: 0

在经过多个小时的调试后,似乎在调用的最后缺少了 server.stop()

这个错误信息有点误导人,但通过调用 netstat -vanp tcp | grep 50051,我能够看到端口似乎被阻塞了,我不得不逐个使用 kill 命令关闭所有应用程序。通过使用 ps aux | grep <pid>,我能够识别出之前运行的服务器仍然存在。

在关闭它们并再次运行测试之后,测试通过了(除了断言失败的部分)。

结论

"StatusCode.UNKNOWN" 可能意味着 端口 被阻塞!

英文:

After many hours debugging, it seems like server.stop() was missing at the end of the call.

It is pretty miss-leading as an error information but calling netstat -vanp tcp | grep 50051 enabled me to see that the port was kind of jammed and I had to kill one by one all the applications. By using ps aux | grep &lt;pid&gt; I could identify that previous running server where still there.

After killing all of them and running the test once more, it went through (besides the assert that is failing)

Conclusion

"StatusCode.UNKNOWN" may mean that the port is blocked!

huangapple
  • 本文由 发表于 2023年6月15日 20:52:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76482686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定