Node.js gRPC部署DigitalOcean报RST_STREAM code 0错误
gRPC部署到DigitalOcean后报
Received RST_STREAM with code 0排查方案 排查步骤按优先级从高到低执行:
1. 先确认服务端本身运行正常
先登录到165.22.201.129这台Droplet本地,写个测试客户端直接连127.0.0.1:9090发请求:
- 如果本地调用也报错,属于服务端自身问题,排查两个点:
- 检查
bindAsync回调里打印的error字段是否为null,确认9090端口没有被其他进程占用、绑定成功 - 对比服务器和本地的
@grpc/grpc-js、@grpc/proto-loader依赖版本,把服务器上的依赖升级到和本地一致的最新稳定版,部分旧版本grpc-js在Linux环境下存在HTTP/2流处理的已知bug - 补全接口返回字段,proto里定义的
EchoResponse包含message_count字段,虽然默认会填充0值,但跨版本时可能触发序列化异常,把回调代码改成callback(null, {message: "response test", message_count: messageCount++})排除序列化问题
- 检查
- 如果本地调用正常,说明服务端代码、运行都没问题,故障出在公网传输链路,继续往下排查。
2. 排查云服务商/系统防火墙拦截(该场景90%的根因)
服务端能收到请求、但客户端收响应时报RST_STREAM错误,几乎都是中间设备拦截HTTP/2流量主动发重置包导致的:
- 先检查DigitalOcean控制面板的云防火墙规则:
- 确认入站规则已经放通9090端口的TCP协议
- 临时关闭防火墙的应用层检测/协议异常拦截类功能,明文gRPC用HTTP/2直连模式(没有HTTP/1.1升级握手),DO的默认防火墙规则会把这类流量识别为异常流量,在回包阶段直接拦截发RST包
- 再检查Droplet系统内部防火墙:
- 执行
ufw status查看ufw是否开启,开启状态下确认放通9090端口的出入站规则,测试阶段可以直接执行ufw disable临时关闭防火墙验证 - 如果用的是firewalld,执行
firewall-cmd --list-all确认端口放通,测试阶段可以临时停止firewalld服务排除干扰
- 执行
3. 排查HTTP/2传输兼容性问题
如果防火墙关了还是报错,做两个调整测试:
- 不要用明文insecure连接,给服务端配置自签名证书,改用TLS加密的gRPC连接。加密后中间设备无法解析流量内容,就不会触发应用层拦截,这也是生产环境gRPC的标准用法
- 客户端创建连接时增加keepalive配置,避免连接被中间设备的空闲连接回收机制切断,配置示例:
const client = new EchoService( "165.22.201.129:9090", grpc.credentials.createInsecure(), { 'grpc.keepalive_time_ms': 10000, 'grpc.http2.max_pings_without_data': 0, 'grpc.keepalive_permit_without_calls': 1 } );
内容的提问来源于stack exchange,提问作者IsolatedSushi
相关产品推荐
相关产品推荐

