多浏览器/标签页发起GraphQL Subscription连接崩溃问题咨询
故障根因
多标签页访问、页面刷新后服务崩溃需等待超时恢复的问题,核心来源于两点:
ariadne==0.13.0版本的GraphQL类实例默认有状态,现有代码全局初始化了一个graphql_server单例,所有Websocket连接共享该实例的会话上下文,新连接建立时会覆盖旧连接的状态变量,直接导致旧连接异常中断,必须等uvicorn配置的websocket超时时间到了才会释放被占用的连接资源。- 现有CORSMiddleware配置的允许方法列表缺少OPTIONS预检请求方法,部分浏览器跨域场景下新建Websocket连接时的预检请求被拦截,会加剧连接冲突。
修复方案
- 调整GraphQL实例的挂载方式,改用工厂函数为每个连接生成独立的GraphQL处理实例,避免状态共享:
SCHEMA = load_schema_from_path("schema.graphql") query = QueryType() subscription = SubscriptionType() schema = make_executable_schema(SCHEMA, [query, subscription]) app = FastAPI() # 移除全局graphql_server单例,每次请求生成新实例 def get_graphql_server(): return GraphQL(schema, debug=True) # 路由绑定改为调用工厂函数返回实例 app.add_route("/graphql", lambda req: get_graphql_server()(req.scope, req.receive, req.send)) app.add_websocket_route("/graphql", lambda ws: get_graphql_server()(ws.scope, ws.receive, ws.send))
- 更新CORSMiddleware配置,补全允许的请求方法:
app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["POST", "GET", "OPTIONS", "WEBSOCKET"], allow_headers=[ "accept", "accept-language", "content-language", "content-type", "x-apollo-tracing", ], )
- 可选优化:如果并发连接量较高,可以将uvicorn的启动参数调整为多worker模式,避免单进程连接上限的问题:
uvicorn.run(app, host='0.0.0.0', port=7996, workers=4)
内容的提问来源于stack exchange,提问作者L. Ollos
相关产品推荐
相关产品推荐

