NestJS GraphQL订阅WebSocket连接AWS API GW遇子协议及后端可达问题
解决AWS WebSocket API Gateway转发GraphQL Transport WS子协议的问题
问题背景
基于NestJS @subscription实现的GraphQL WebSocket订阅服务部署在AWS ECS,前端通过ALB/NLB + WebSocket API Gateway + VPC Link对外提供服务。本地环境执行wscat -c ws://localhost:3000/graphql -s graphql-transport-ws可正常连接,但通过API GW访问时出现以下问题:
- 指定
graphql-transport-ws子协议会报错error: Server sent no subprotocol - 移除子协议能连接API GW,但流量无法到达后端;直接连接公网NLB则正常。
解决方案
1. 配置WebSocket API Gateway转发子协议头
AWS WebSocket API GW默认不会转发WebSocket握手的子协议请求头,也不会回传后端的确认头,需要手动配置:
- 进入WebSocket API的集成请求(绑定VPC Link的集成),添加自定义头映射:
- 键:
Sec-WebSocket-Protocol - 值:
$context.request.header.Sec-WebSocket-Protocol
- 键:
- 进入集成响应,添加响应头映射:
- 键:
Sec-WebSocket-Protocol - 值:
$context.response.header.Sec-WebSocket-Protocol
- 键:
- 确保API阶段设置中未禁用WebSocket相关的头转发功能。
2. 确保VPC Link类型匹配
WebSocket API Gateway仅支持REST类型的VPC Link,HTTP API的VPC Link无法兼容。如果之前复用了HTTP API的VPC Link,需要重新创建REST类型的VPC Link并绑定到NLB/ALB。
3. 验证NestJS后端配置
确认NestJS的GraphQL订阅配置明确启用了graphql-transport-ws子协议:
GraphQLModule.forRoot({ subscriptions: { 'graphql-transport-ws': { path: '/graphql', }, }, // 其他GraphQL配置项 });
4. 流量排查步骤
- 查看CloudWatch中的WebSocket API Gateway日志,确认请求是否进入集成阶段,是否存在路由错误。
- 检查NLB/ALB的访问日志,确认API GW的请求是否到达负载均衡器。
- 在ECS容器内用
tcpdump抓包,验证WebSocket握手请求是否到达后端服务。
内容的提问来源于stack exchange,提问作者Bear
相关产品推荐
相关产品推荐

