GraphQL订阅无法连接WebSocket端点问题求助
GraphQL订阅WebSocket连接失败问题排查
问题描述
我是GraphQL新手,尝试创建订阅功能时出现以下错误:
无法连接到WebSocket端点ws://localhost:3000/graphql。请检查端点URL是否正确。
参考官方文档编写的代码如下:
const { createServer } = require('http') const express = require('express') const { ApolloServer } = require('apollo-server-express') const { ApolloServerPluginDrainHttpServer } = require('apollo-server-core') const { PubSub } = require('graphql-subscriptions') const { WebSocketServer } = require('ws') const { useServer } = require('graphql-ws/lib/use/ws') const { env } = require('../config/index') const schema = require('./schema') const models = require('../db/models') const getAuthUser = require('../utils/authorization') const pubSub = new PubSub() const app = express() const httpServer = createServer(app) const wsServer = new WebSocketServer({ server: httpServer, path: '/graphql' }) const serverCleanup = useServer({ schema }, wsServer) const server = new ApolloServer({ schema, csrfPrevention: true, cache: 'bounded', plugins: [ // Proper shutdown for the HTTP server. ApolloServerPluginDrainHttpServer({ httpServer }), // Proper shutdown for the WebSocket server. { async serverWillStart() { return { async drainServer() { await serverCleanup.dispose() }, } }, }, ], playground: env.development, context: async ({ req }) => { const token = req.headers.authorization const user = getAuthUser(token) return { models, user, pubSub } }, }) server.applyMiddleware({ app }) server.installSubscriptionHandlers(httpServer) module.exports = { server, httpServer }
另一文件中已调用httpServer.listen(port)启动服务,请问该错误产生的原因是什么?有哪些解决建议?
可能的原因
- 重复配置WebSocket服务:同时使用
graphql-ws的useServer和Apollo Server的installSubscriptionHandlers,两种方式均用于配置WebSocket订阅服务,会引发端口冲突或服务启动异常。Apollo Server 3+推荐使用graphql-ws集成方式,installSubscriptionHandlers属于旧版订阅处理方法,二者共存会造成冲突。 - WebSocket上下文缺失:当前
context函数仅处理HTTP请求的req对象,但WebSocket连接的上下文需要单独处理。若未在graphql-ws的配置中定义上下文逻辑,可能导致连接时权限验证或数据获取失败,间接引发连接问题。 - 端口/路径不匹配:若
httpServer.listen(port)中的port并非3000,或3000端口被其他程序占用,会导致客户端无法连接到指定端点。
解决建议
- 移除重复订阅配置:删除
server.installSubscriptionHandlers(httpServer)代码行,已通过graphql-ws的useServer完成WebSocket服务配置,无需保留旧版处理逻辑。 - 完善WebSocket上下文处理:在
useServer配置中添加context选项,处理WebSocket连接的上下文(比如从连接参数中获取token):
const serverCleanup = useServer({ schema, context: async (ctx) => { const token = ctx.connectionParams?.authorization; const user = getAuthUser(token); return { models, user, pubSub }; }, }, wsServer);
- 验证端口与路径:确认
httpServer.listen(port)中的port为3000,或修改客户端连接URL为实际端口。检查端口占用情况:- Mac/Linux:运行
lsof -i :3000 - Windows:运行
netstat -ano | findstr :3000
若端口被占用,更换为未被使用的端口。
- Mac/Linux:运行
- 检查依赖版本兼容性:确保
apollo-server-express、graphql-ws等依赖版本兼容。Apollo Server 3.x需搭配graphql-ws,而非旧版的subscriptions-transport-ws。运行npm list查看依赖版本,必要时更新至兼容版本。
内容的提问来源于stack exchange,提问作者Garth McCallister
相关产品推荐
相关产品推荐

