Files
qing c4154d4db9 feat(gomsg): pymsg/libmsg 协议的 Go 实现,waf logclient 抽取接入
- 新增 gomsg/:帧协议(4B 大端长度 + UTF-8,64MiB 上限)、MsgClient/MsgServer、
  RpcClient/RpcServer(_route 分发、错误脱敏、panic 恢复、json.Number 保精度)、
  AsyncQueue[T]、LogClient(集中式日志,级别过滤 + fail-safe),线协议与 Python/C++ 字节级兼容
- waf/internal/logclient 改为 gomsg 薄适配层(336→20 行),main/engine/proxy 零改动
- gomsg 26 项单测全绿(-race);waf 编译通过
2026-08-23 11:21:40 +00:00

3.4 KiB
Raw Permalink Blame History

gomsg — pymsg / libmsg 协议的 Go 实现

Go 版消息通信库,对应 Python pymsg 与 C++ libmsg,线协议字节级兼容:

[4 字节 big-endian uint32 长度][UTF-8 载荷]        (单条上限 64 MiB)

模块组成

文件 内容 对应
frame.go 帧编解码:Encode / WriteFrame / ReadFrame(长度上限防护) pymsg send/recv
client.go MsgClient:复用长连接 + 请求-响应 + 失败重连一次 pymsg MsgClient
server.go MsgServer:accept 循环 + 每连接 goroutine 串行处理 pymsg MsgServer
rpc.go RpcClient / RpcServer / RpcError:_route 分发、错误脱敏、panic 恢复 pymsg rpc.py
asyncqueue.go AsyncQueue[T]:批量 + 定时 flush,满队列丢新数据(fail-safe) libmsg AsyncQueue
logclient.go LogClient:异步批量推送 db2 Logs 表(级别过滤 + fail-safe) waf internal/logclient、log_client.py、liblogc

使用

// RPC 调用(如调 db2 execute 路由)
rpc := gomsg.NewRpcClient("127.0.0.1:8005", 5*time.Second)
data, err := rpc.Call("execute", map[string]any{
    "action": "select", "table": "Users",
})
// data 为 any:数字是 json.Number(保 int64 精度),需用 .Int64()/.Float64() 转换

// 提供 RPC 服务
srv := gomsg.NewRpcServer("127.0.0.1:8009")
srv.AddRoute("health", func(req map[string]any) (any, error) { return map[string]any{"ok": true}, nil })
if err := srv.Start(); err != nil { ... }
defer srv.Stop()

// 集中式日志(写入 db2 Logs 表)
lc := gomsg.NewLogClient("127.0.0.1:8005")
lc.SetLevel("info")
lc.Info("backend", "服务启动", nil)
defer lc.Flush() // 进程退出前 flush

与 Python / C++ 的兼容约定

  • 请求:{"_route": "<路由名>", ...业务字段}(_route 在分发前被弹出,handler 看不到)
  • 响应:{"success": true, "data": ...} / {"success": false, "error": "..."}
  • 未知路由:{"success": false, "error": "未知路由: <route>"}
  • 非法 JSON:{"success": false, "error": "invalid JSON request"}(不回显输入片段)
  • 错误脱敏:异常信息中的绝对路径替换为 <redacted>(对齐 Python _sanitize_error)
  • handler panic:自动恢复并包装为 success=false(对应 Python 的 except Exception)

安全性

  • 帧长度上限 64 MiB 在读写两侧强制(恶意长度前缀不会导致内存耗尽)
  • 请求 JSON 解析:Go encoding/json 内置 10000 层嵌套上限;数字经 UseNumber 以字符串保存, 超大数字不会触发 CPU 密集型解析;输入大小受帧上限约束
  • 异常信息脱敏,不透传绝对路径等内部细节
  • 数字一律 json.Number 保留原始精度,避免 int64 ID 经 float64 丢失

测试

go test ./... -count=1 -race

覆盖:帧往返/超限/截断、Client-Server 回环、自动重连、并发客户端、RPC 成功/失败/脱敏/ 未知路由/非法 JSON/panic 恢复/超时、AsyncQueue 批量/定时/关停 drain/满队列丢弃、 LogClient 对假 db2 服务的推送与级别过滤、db2 不可用时 fail-safe。

来源

MsgClient 连接复用与 LogClient 逻辑抽取自 waf/internal/logclient; API 与协议约定对齐 pymsg(Python)与 libmsg(C++)。