Apollo Server V3 Subscription无法监听WebSocket连接问题
Apollo Server V3 WebSocket订阅连接失败排查修复
以下是按优先级排序的故障点和对应修复方案,全部修改完成后即可正常使用订阅功能:
- 修正
graphql-ws服务初始化配置,补全上下文注入
现有代码中useServer仅传入了schema,没有注入WebSocket链路所需的上下文,订阅执行时拿不到pubsub实例会直接中断连接。将原有初始化代码替换为:const serverCleanup = useServer({ schema, context: async (ctx) => { // 可在此处添加WebSocket连接鉴权逻辑,例如从连接参数解析token return { pubsub }; }, }, wsServer); - 修正异步资源初始化顺序,等待MongoDB连接完成后再启动服务
现有代码中mongoose.connect没有加await,服务启动监听时数据库可能尚未完成连接,若resolver存在数据库依赖逻辑,会直接导致WebSocket握手失败。修改数据库连接代码:
注意将该段代码放在await mongoose.connect(MONGODB, { useNewUrlParser: true, useUnifiedTopology: true });server.applyMiddleware之后、httpServer.listen之前执行。 - 补全跨域配置,避免浏览器拦截WebSocket握手请求
现有代码没有配置CORS规则,本地开发时前端与服务端端口不一致,浏览器会直接拦截跨域的WebSocket请求。先安装cors依赖:
之后在express初始化后加载全局cors中间件:npm install corsconst app = express(); const cors = require('cors'); app.use(cors({ origin: "*", // 生产环境替换为实际前端业务域名 credentials: true })); - 检查客户端协议匹配性
服务端使用graphql-ws库实现WebSocket服务,遵循graphql-transport-ws协议,若客户端仍使用已废弃的subscriptions-transport-ws库,会因协议不匹配直接连接失败。客户端需替换为graphql-ws库做连接初始化,禁止使用旧版WebSocketLink适配包。 - 额外校验点
检查订阅resolver中pubsub.asyncIterator监听的事件名,和对应Mutation中pubsub.publish触发的事件名完全一致,避免拼写错误导致订阅触发无响应;本地开发阶段内存版PubSub可正常运行,多实例部署时需替换为Redis等跨实例的PubSub实现。
修复完成后重启服务,可直接通过Postman的WebSocket调试功能连接
ws://localhost:5002/graphql验证握手状态,无需先打开前端页面即可排查服务端问题。
内容的提问来源于stack exchange,提问作者Kelum
相关产品推荐
相关产品推荐

