6.0 KiB
6.0 KiB
collab-go
实时协作文档编辑的 WebSocket 网关。负责 JWT 鉴权并将协作流量代理到 collab-core。
概述
collab-go 是一个 Go 服务,作为 Yoresee Doc 协作编辑平台中浏览器 WebSocket 连接的入口。主要职责:
- JWT 令牌校验(HS256/384/512)
- 通过 gRPC 调用后端校验文档是否存在
- 与
collab-core(Node.js Yjs 服务)之间的双向 WebSocket 代理 - 健康检查与优雅停机
连接流程
浏览器 --ws://host/ws/doc/{docId}?token={jwt}--> collab-go --> collab-core
- 浏览器连接
/ws/doc/{docId},JWT 通过 query 参数传递 collab-go校验 JWT 令牌collab-go调用后端 gRPCDocumentService.GetDocumentSettings()验证文档存在- 成功后将 HTTP 升级为 WebSocket
- 拨号连接
collab-core:{COLLAB_CORE_URL}/doc-{docId} - 在浏览器与
collab-core之间双向代理消息
前置依赖
Proto 桩代码
pkg/gen/ 包含生成的 protobuf 代码,已被 gitignore。构建前必须先生成:
# 推荐:使用父仓库脚本
bash ../deploy/script/gen_proto.sh
# 或手动 protoc
mkdir -p pkg/gen
protoc -I ../proto \
--go_out=pkg/gen --go_opt=paths=source_relative \
--go-grpc_out=pkg/gen --go-grpc_opt=paths=source_relative \
../proto/yoresee_doc/v1/yoresee_doc.proto
所需工具:
protoc-gen-go:go install google.golang.org/protobuf/cmd/protoc-gen-go@latestprotoc-gen-go-grpc:go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Go
Go 1.24 或更高版本。
构建与运行
# 构建
go build -o collab-go main.go
# 运行
./collab-go
或直接运行:
go run main.go
默认端口:1234
配置
环境变量:
| 变量 | 默认值 | 必填 | 说明 |
|---|---|---|---|
ADDR |
:1234 |
否 | 监听地址 |
JWT_SECRET |
(空) | 是 | JWT 签名密钥。为空 = 接受任何可解析的 JWT(开发模式) |
COLLAB_CORE_URL |
ws://collab-core:1234 |
否 | collab-core 的 WebSocket 地址 |
BACKEND_GRPC_ADDR |
backend:9090 |
否 | 后端 gRPC 地址 |
INTERNAL_RPC_KEY |
(空) | 否 | 作为 x-internal-key gRPC 元数据发送,用于内部鉴权 |
JWT 模式
生产模式(设置了 JWT_SECRET):
- 使用 HS256/384/512 校验 JWT 签名
- 令牌必须有效且签名正确
开发模式(JWT_SECRET 为空):
- 解析 JWT 但不校验签名
- 接受任何结构有效的 JWT
- 适用于本地开发时无共享密钥的场景
API 端点
WebSocket
GET /ws/doc/{docId}?token={jwt}
- 成功后升级为 WebSocket
- JWT 无效返回
401 Unauthorized - 文档不存在返回
404 Not Found - 后端 gRPC 不可达返回
503 Service Unavailable
健康探针
GET /health
GET /readyz
GET /livez
均返回 JSON:
{
"status": "ok",
"detail": "",
"backend": "ok"
}
/health:始终返回200 OK。包含后端状态(如可用)。/readyz:停机 draining 阶段或后端不健康时返回503 Service Unavailable。/livez:始终返回200 OK。用于存活检查。
架构
collab-go/
├── auth/ JWT 校验
├── config/ 基于环境变量的配置
├── handler/ WebSocket 处理器:鉴权 + 文档校验 + 代理
├── health/ 健康探针处理器
├── proxy/ 双向 WebSocket 代理
├── pkg/gen/ 生成的 protobuf 桩代码(gitignored)
└── main.go 入口文件
核心组件
auth/
Authenticator校验 JWT 令牌- 支持 HS256、HS384、HS512 签名方式
- 密钥为空时降级为不校验签名的解析
config/
- 使用
caarlos0/env/v11解析环境变量 - 所有配置通过环境变量传入
handler/
WSHandler实现 WebSocket 连接的http.Handler- 从
?token=query 参数获取 JWT - 调用后端 gRPC 校验文档是否存在
- 升级连接后委托给代理
health/
- 实现 Kubernetes 风格的健康探针
- readiness 检查后端 gRPC 健康状态
- 支持优雅停机 draining
proxy/
Proxy管理与collab-core的 WebSocket 连接ProxyWS启动两个 goroutine 进行双向消息转发- 连接路径:
collab-core上的/doc-{docId}
优雅停机
收到 SIGINT 或 SIGTERM 信号后:
- 健康检查器进入 draining 模式(readiness 返回
not_ready) - 停止接受新连接
- 等待已有连接关闭,最长 15 秒
- 退出
负载均衡器应在 /readyz 返回非 200 时停止路由流量。
Docker
开发环境
docker build -t collab-go-dev -f Dockerfile .
docker run -p 1234:1234 --env-file .env collab-go-dev
运行 go run main.go(无构建缓存)。
生产环境
# 从父目录构建
docker build -t collab-go -f Dockerfile.prod ..
注意:Dockerfile.prod 期望构建上下文在父目录(..),因为它需要复制:
collab-go/源码proto/用于 protobuf 生成- 在容器内部生成 proto 桩代码
多阶段构建:
- Builder 阶段:生成 proto 桩代码,编译二进制
- Runner 阶段:将二进制复制到最小化 Alpine 镜像
协作栈集成
collab-go 是双服务协作栈的一部分:
- collab-core(Node.js):在内存 + Redis 中维护 Yjs 文档状态
- collab-go(Go):WebSocket 网关,鉴权,代理
网关模式实现了职责分离:
- 鉴权与授权(Go,快速)
- 文档状态管理(Node.js,Yjs 运行时)
- 水平扩展(多个网关实例,每个文档一个 core)
日志
所有日志使用 collab-gateway 前缀:
collab-gateway listening on :1234
collab-gateway unauthorized path=/ws/doc/abc remote=127.0.0.1:12345 err=...
collab-gateway doc check failed docID=abc err=...
测试
当前无测试。可通过以下命令验证:
go vet ./...
go build ./...
相关文档
- 父项目:
../AGENTS.md - 完整系统文档:
../../docs/README.md - 中文版本:
../../docs/README_zh.md