grpc.aio + uvloop抛出BlockingIOError问题求助
grpc.aio 迁移后反复触发 BlockingIOError 问题排查与求助
问题现象
将Python服务从asyncio.to_thread(...)包装的同步grpcio调用迁移到原生grpc.aio以降低单调用延迟后,事件循环中反复抛出以下错误:
ERROR:asyncio:Exception in callback PollerCompletionQueue._handle_events(...) Traceback (most recent call last): File "/opt/homebrew/Cellar/python@3.11/3.11.13/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/events.py", line 84, in _run self._context.run(self._callback, *self._args) File "src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi", line 148, in grpc._cython.cygrpc.PollerCompletionQueue._handle_events BlockingIOError: [Errno 35] Resource temporarily unavailable
切换为uvloop运行时,回调路径仍会出现相同问题。
代码变更对比
- 迁移前(同步grpcio + asyncio.to_thread包装):
response = await asyncio.to_thread( self.stub.Predict, request, timeout=timeout )
- 迁移后(原生grpc.aio):
启动阶段创建并预热异步gRPC通道/存根:
manager = AsyncGrpcChannelManager() await manager.warm_up() stub = await manager.get_stub() resp = await stub.LoadModel(load_req, timeout=timeout)
环境信息
- Python 3.11.13
- grpcio==1.76.0
- uvloop==0.22.1
- 运行于Granian环境
疑问
这是否是grpc.aio与uvloop/Granian之间的已知兼容性问题?尝试过多种方法仍未解决,恳请提供排查方向或解决方案。
排查与解决方向
- 调整grpcio版本:grpc.aio在部分版本中对uvloop的支持存在细节缺陷,建议升级至最新稳定版(如1.78.x及以上),或降级至1.74.x版本测试,已有用户反馈这些版本能缓解该错误。
- Granian事件循环配置:Granian默认使用自身的事件循环适配,启动时需明确指定兼容模式,比如添加
--loop uvloop参数;同时检查代码中是否存在事件循环嵌套或资源竞争的情况。 - 通道生命周期管理:检查
AsyncGrpcChannelManager的实现,确保异步通道是单例复用,避免频繁创建销毁导致文件句柄波动;确认warm_up逻辑是否完成了通道连接池的初始化,未预热完成就发起请求可能触发资源临时不可用错误。 - 调高系统资源限制:Errno 35对应资源临时不可用,检查系统文件描述符限制(执行
ulimit -n查看),grpc.aio异步操作会占用更多文件句柄,建议将限制调高至65535。 - 指定gRPC Poll策略:通过环境变量强制指定Poll策略,Linux环境设置
GRPC_POLL_STRATEGY=epoll1,macOS设置GRPC_POLL_STRATEGY=kqueue,避免自动选择的策略与uvloop/Granian冲突;也可尝试设置GRPC_AIO_ENABLE_WORKAROUNDS=1启用兼容性补丁。
内容的提问来源于stack exchange,提问作者anish
相关产品推荐
相关产品推荐

