使用pygNMi监听WebSocket收数据遇grpc._channel._MultiThreadedRendezvous错误求助
解决gNMI订阅时
grpc._channel._MultiThreadedRendezvous: Channel closed!错误 核心问题分析
你的代码存在两个直接导致通道关闭的问题:
- 上下文管理器作用域错误:遍历
telemetry_stream的代码写在with gNMIclient(...) as gc:块之外,with块执行完毕后客户端会自动断开连接,此时再迭代流就会触发通道关闭报错。 - 订阅路径为空:
path字段是空字符串,Ciena设备不接受空路径的订阅请求,服务端会直接关闭连接。
另外还有逻辑隐患:subscribe和host_entry定义在for循环内,若存在多个Ciena设备,最终只会使用最后一个设备的配置;如果没有匹配设备,host_entry会处于未定义状态。
修正后的代码
from pygnmi.client import gNMIclient, telemetryParser from inventory import hosts import pprint def subscribe_to_device(host_entry): # 替换为Ciena设备支持的实际gNMI订阅路径,比如性能监控相关路径 subscribe_config = { 'subscription': [ { 'path': '/pm/telemetry', # 示例路径,请替换为设备真实路径 'mode': 'sample', 'sample_interval': 10000000000 # 10秒采样间隔 } ], 'mode': 'stream', 'encoding': 'proto' } # 流遍历逻辑必须放在with块内,保持连接活跃 with gNMIclient(target=(host_entry["ip_address"], host_entry["port"]), username=host_entry["username"], password=host_entry["password"], skip_verify=True, debug=True) as gc: telemetry_stream = gc.subscribe(subscribe=subscribe_config) for telemetry_entry in telemetry_stream: raw_data = telemetryParser(telemetry_entry) pp = pprint.PrettyPrinter(indent=2) pp.pprint(raw_data) if __name__ == '__main__': # 遍历所有Ciena设备并逐一处理订阅 for host_entry in hosts: if host_entry["nos"] == "Ciena": print(f"启动订阅设备: {host_entry['ip_address']}") subscribe_to_device(host_entry)
关键修复点
- 调整上下文作用域:将流遍历代码移入
with块内部,确保在客户端连接存续期间处理数据。 - 填充合法订阅路径:必须指定设备支持的有效gNMI路径,可通过设备的gNMI schema文档或
get操作查询可用路径。 - 优化逻辑结构:将单设备订阅封装为函数,遍历匹配设备时逐个执行,避免变量覆盖问题。
额外排查建议
- 确认设备端gNMI服务已启用,且端口(通常为57400)处于开放状态。
- 检查账号是否具备gNMI订阅权限。
- 借助
debug=True输出的gRPC日志,查看服务端返回的具体错误细节。
内容的提问来源于stack exchange,提问作者user23453475
相关产品推荐
相关产品推荐

