Skip to content

Go WebSocket 网关

网关是分布式架构的入口,负责将客户端连接分发到多个 IM 后端实例。

工作原理

客户端 A ──┐
客户端 B ──┼──▶ Go 网关 (:8080) ──┬──▶ IM 实例 1 (:3000)
客户端 C ──┤                      ├──▶ IM 实例 2 (:3001)
客户端 D ──┘                      └──▶ IM 实例 3 (:3002)

网关对客户端透明:所有 WebSocket 连接和 HTTP 请求都通过网关统一入口,网关内部选择后端实例进行转发。

核心功能

WebSocket 代理:客户端与网关建立 WebSocket 连接后,网关选择一个健康的后端实例,与之建立上游 WebSocket 连接,然后双向透传消息帧。

HTTP API 代理:REST API 请求同样通过网关转发到后端,客户端只需知道网关地址。

健康检查:网关定期探测后端实例,自动摘除不健康的节点,恢复后自动加回。

负载均衡:默认使用 Round-Robin(轮询)策略,均匀分配连接到各后端。

配置文件

网关配置位于 server/gateway/gateway.yaml

yaml
port: 8080              # 网关监听端口

backends:               # 后端 IM 实例列表
  - ws://localhost:3000
  - ws://localhost:3001
  - ws://localhost:3002

balance_mode: round_robin   # 负载均衡策略(当前仅支持 round_robin)
health_check: true          # 是否启用健康检查
health_interval: 10         # 健康检查间隔(秒)

编译

需要安装 Go 1.21+:

bash
cd server/gateway

# 编译当前平台
go build -o ../dist/im-gateway

# 交叉编译 Linux
GOOS=linux GOARCH=amd64 go build -o ../dist/im-gateway-linux

# 交叉编译 Windows
GOOS=windows GOARCH=amd64 go build -o ../dist/im-gateway.exe

也可以从项目根目录通过 npm 脚本编译:

bash
npm run build:gateway:linux

部署

将编译好的 im-gateway 二进制放到服务器上,确保 gateway.yaml 在同目录下:

/opt/im/
├── im-gateway          # Go 网关二进制
├── gateway.yaml        # 网关配置
├── im-server-1/        # IM 实例 1
│   ├── im-server
│   └── config.yaml
├── im-server-2/        # IM 实例 2
│   ├── im-server
│   └── config.yaml
└── im-server-3/        # IM 实例 3
    ├── im-server
    └── config.yaml

启动顺序:先启动各 IM 后端实例,再启动网关。

bash
# 启动后端实例(每个实例不同端口)
cd im-server-1 && PORT=3000 STORAGE=mysql MESSENGER=redis ./im-server &
cd im-server-2 && PORT=3001 STORAGE=mysql MESSENGER=redis ./im-server &
cd im-server-3 && PORT=3002 STORAGE=mysql MESSENGER=redis ./im-server &

# 启动网关
./im-gateway

前端对接

前端只需将连接地址改为网关地址:

javascript
// config.js
const config = {
  imBaseURL: 'https://chat.example.com',   // 指向网关
  wsURL: 'wss://chat.example.com',          // 指向网关
}

网关会自动将请求转发到后端,前端无需感知多实例的存在。

Nginx 反代(推荐)

生产环境建议在网关前再加一层 Nginx 处理 TLS 终止和静态资源:

nginx
upstream im_gateway {
    server 127.0.0.1:8080;
}

server {
    listen 443 ssl;
    server_name chat.example.com;

    ssl_certificate     /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/key.pem;

    # WebSocket
    location /ws {
        proxy_pass http://im_gateway;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
    }

    # REST API
    location /api/ {
        proxy_pass http://im_gateway;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 静态资源
    location / {
        proxy_pass http://im_gateway;
    }
}