You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让graphql-ws基于HTTP/2使用WebSocket连接?

解决方案:GraphQL订阅WebSocket在HTTP/2架构下的适配问题

针对你描述的Traefik反向代理+仅HTTP/2后端的架构中,GraphQL订阅WebSocket无法正常工作的问题,以下是三个方向的具体解决方案:

方向1:配置GraphQL客户端强制复用HTTP/2连接

浏览器的WebSocket是否使用HTTP/2模式,依赖于是否复用已建立的HTTP/2连接。你可以通过调整graphql-ws客户端配置,确保订阅请求复用与普通GraphQL请求相同的HTTP/2连接:

  • 对于Apollo Client,配置WebSocket链接时启用连接复用,避免新建独立连接:
import { createWebSocketLink } from '@apollo/client/link/ws';
import { createHttpLink, split } from '@apollo/client';
import { getMainDefinition } from '@apollo/client/utilities';

// 普通HTTP/2请求链接
const httpLink = createHttpLink({ uri: 'https://your-domain.com/graphql' });

// WebSocket链接,启用懒加载关闭+连接复用
const wsLink = createWebSocketLink({
  uri: 'wss://your-domain.com/graphql',
  lazy: false, // 提前建立连接,复用HTTP/2会话
  connectionParams: {
    // 可选:传递认证token等参数
  },
});

// 根据操作类型自动选择传输方式
const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLink
);
  • 验证:在浏览器Network面板中,查看WebSocket请求的Connection列,确认其复用了与普通请求相同的HTTP/2连接ID。

方向2:调整Traefik与后端配置,触发浏览器自动使用HTTP/2 WebSocket

根据Chromium的规则,浏览器自动使用HTTP/2 WebSocket需要服务器支持CONNECT方法转发。你需要调整Traefik路由和后端服务的处理逻辑:

1. Traefik配置(支持CONNECT方法转发)

在Traefik动态配置中添加专门处理CONNECT请求的路由,确保转发到后端的h2c服务:

http:
  routers:
    graphql-ws-http2:
      rule: "Host(`your-domain.com`) && Method(`CONNECT`) && Path(`/graphql`)"
      service: graphql-backend
      tls: {} # 保留Traefik的TLS终止
  services:
    graphql-backend:
      loadBalancer:
        servers:
          - url: "h2c://backend:4000"
        http2:
          enabled: true # 强制启用HTTP/2转发

2. 后端HTTP/2服务器配置(处理CONNECT请求)

确保后端HTTP/2服务器能够识别CONNECT请求并升级为WebSocket。以Node.js为例:

const http2 = require('http2');
const WebSocket = require('ws');

const server = http2.createServer();
const wss = new WebSocket.Server({ noServer: true });

// 处理HTTP/2的CONNECT请求,升级为WebSocket
server.on('CONNECT', (req, socket, head) => {
  if (req.url === '/graphql') {
    wss.handleUpgrade(req, socket, head, (ws) => {
      wss.emit('connection', ws, req);
      // 后续处理GraphQL订阅逻辑
    });
  } else {
    socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
    socket.destroy();
  }
});

// 处理普通GraphQL HTTP/2请求
server.on('stream', (stream, headers) => {
  // 你的GraphQL请求处理逻辑
});

server.listen(4000);

3. 验证

在Chrome的chrome://net-internals/#http2页面查看连接详情,确认WebSocket连接使用的是HTTP/2协议的CONNECT方法。

方向3:后端实现多协议支持,无需管理TLS

如果不想修改客户端或Traefik的转发规则,可以让后端同时支持h2c(HTTP/2明文)和HTTP/1.1,TLS仍由Traefik管理:

1. 后端多协议服务器配置

创建支持HTTP/1.1和h2c的multi-use服务器,无需配置TLS证书。以Node.js为例:

const http2 = require('http2');
const WebSocket = require('ws');

// 创建同时支持HTTP/1.1和h2c的服务器
const server = http2.createServer({ allowHTTP1: true });
const wss = new WebSocket.Server({ noServer: true });

// 处理HTTP/1.1的WebSocket Upgrade请求
server.on('upgrade', (req, socket, head) => {
  if (req.url === '/graphql') {
    wss.handleUpgrade(req, socket, head, (ws) => {
      wss.emit('connection', ws, req);
    });
  } else {
    socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
    socket.destroy();
  }
});

// 处理HTTP/2和HTTP/1.1的普通请求
server.on('stream', (stream, headers) => {
  // 你的GraphQL请求处理逻辑
});

server.listen(4000);

2. Traefik路由配置

配置两个路由,分别转发普通HTTP/2请求和WebSocket Upgrade请求:

http:
  routers:
    graphql-http2:
      rule: "Host(`your-domain.com`) && Path(`/graphql`) && !Header(`Upgrade`, `websocket`)"
      service: graphql-backend-h2c
      tls: {}
    graphql-ws:
      rule: "Host(`your-domain.com`) && Path(`/graphql`) && Header(`Upgrade`, `websocket`)"
      service: graphql-backend-http1
      tls: {}
  services:
    graphql-backend-h2c:
      loadBalancer:
        servers:
          - url: "h2c://backend:4000"
    graphql-backend-http1:
      loadBalancer:
        servers:
          - url: "http://backend:4000"

这样Traefik会自动区分请求类型,将普通HTTP/2请求转发到h2c后端,WebSocket请求转发到HTTP/1.1后端,后端无需管理TLS证书。

内容的提问来源于stack exchange,提问作者floge07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 08:35:18