Files
collab-go/docs/README_zh.md
T
2026-08-11 14:16:15 +08:00

243 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```
1. 浏览器连接 `/ws/doc/{docId}`,JWT 通过 query 参数传递
2. `collab-go` 校验 JWT 令牌
3. `collab-go` 调用后端 gRPC `DocumentService.GetDocumentSettings()` 验证文档存在
4. 成功后将 HTTP 升级为 WebSocket
5. 拨号连接 `collab-core`:`{COLLAB_CORE_URL}/doc-{docId}`
6. 在浏览器与 `collab-core` 之间双向代理消息
## 前置依赖
### Proto 桩代码
`pkg/gen/` 包含生成的 protobuf 代码,已被 gitignore。构建前必须先生成:
```bash
# 推荐:使用父仓库脚本
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@latest`
- `protoc-gen-go-grpc`:`go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest`
### Go
Go 1.24 或更高版本。
## 构建与运行
```bash
# 构建
go build -o collab-go main.go
# 运行
./collab-go
```
或直接运行:
```bash
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:
```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` 信号后:
1. 健康检查器进入 draining 模式(readiness 返回 `not_ready`)
2. 停止接受新连接
3. 等待已有连接关闭,最长 15 秒
4. 退出
负载均衡器应在 `/readyz` 返回非 200 时停止路由流量。
## Docker
### 开发环境
```bash
docker build -t collab-go-dev -f Dockerfile .
docker run -p 1234:1234 --env-file .env collab-go-dev
```
运行 `go run main.go`(无构建缓存)。
### 生产环境
```bash
# 从父目录构建
docker build -t collab-go -f Dockerfile.prod ..
```
注意:`Dockerfile.prod` 期望构建上下文在父目录(`..`),因为它需要复制:
- `collab-go/` 源码
- `proto/` 用于 protobuf 生成
- 在容器内部生成 proto 桩代码
多阶段构建:
1. Builder 阶段:生成 proto 桩代码,编译二进制
2. Runner 阶段:将二进制复制到最小化 Alpine 镜像
## 协作栈集成
`collab-go` 是双服务协作栈的一部分:
1. **collab-core**(Node.js):在内存 + Redis 中维护 Yjs 文档状态
2. **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=...
```
## 测试
当前无测试。可通过以下命令验证:
```bash
go vet ./...
go build ./...
```
## 相关文档
- 父项目:`../AGENTS.md`
- 完整系统文档:`../../docs/README.md`
- 中文版本:`../../docs/README_zh.md`