@go/discover
Maintainer Statement: 本项目完全由 AI 维护。任何改动均遵循代码质量与性能的最佳实践。
@go/discover 是一个无状态、参数驱动的极简服务发现与负载均衡组件。它基于 Redis 实现,专注于消除微服务调用间的摩擦,并原生支持 Header 链路透传。
🎯 设计哲学
- 纯粹无状态 (Stateless):模块自身不读取配置文件,不依赖任何特定框架的上下文。它是一个纯粹的函数式库,配置的加载权力完全交给顶层(如
@go/service)。 - 面向对象隔离:支持多实例共存。你可以在同一个进程中同时连接不同的注册中心,实现复杂的网关分发。
- 内存安全与高性能:敏感令牌 (Token) 受
@go/safe内存保护;调用耗时由@go/timer高性能打点引擎追踪;网络层支持 H2C (HTTP/2 Cleartext)。
📦 安装
go get apigo.cc/go/discover
💡 快速入门 (Quick Start)
1. 服务端模式 (Server)
如果你是一个需要被别人发现的服务,使用 Start。
import "apigo.cc/go/discover"
// 可选配置
conf := discover.Config{
Weight: 100,
Calls: map[string]string{
"auth-service": "1s:my-token", // 依赖外部 auth 服务,超时1s,附加令牌
},
}
// 启动并注册 (注册中心地址, 我的服务名, 我的可访问地址, 可选配置)
d := discover.Start("redis://127.0.0.1:6379/15", "user-service", "198.18.0.1:8080", conf)
defer d.Stop() // 优雅注销
2. 纯客户端模式 (Client)
如果你只是一个脚本或 API 网关,只需要调用别人,使用 Open。
// 启动纯客户端 (注册中心地址, 可选配置)
d := discover.Open("redis://127.0.0.1:6379/15")
🛠 API Reference (实例方法)
Start 和 Open 均会返回一个 *discover.Discoverer 实例,所有的业务调用都应通过此实例进行。
1. 泛型快捷调用 (Stateless Data Fetching)
自动解析 JSON 响应到结构体,适用于绝大多数简单的 RPC 场景。
type User struct { ID int }
// Get[T] / Post[T] / Put[T] / Delete[T]
user, err := discover.Get[User](d, "user-service", "/api/info")
2. 链路透传调用 (Stateful Context Propagation)
在微服务网状网络中,我们需要将前置网关的 TraceID, UserID, X-Real-IP 等信息继续向后透传。使用 From(r) 包装器可以极其优雅地实现。
func MyHandler(w http.ResponseWriter, r *http.Request) {
// d 假设是你的全局发现实例
// From 会自动提取 r 中的上下文 Header 并发送给 user-service
res := d.From(r).Post("user-service", "/create", reqData)
// 或者结合泛型
user, err := gohttp.To[User](d.From(r).Get("user-service", "/info"))
}
3. 直接获取结果 (Raw Result)
兼容 @go/http 模块的 *Result 对象,便于处理非 JSON 响应或检查原始 HTTP 状态码。
res := d.Do("GET", "auth-service", "/verify", nil)
if res.Error == nil {
fmt.Println(res.String())
// 也可以: res.Save("file.txt")
}
4. WebSocket 支持
无缝升级为 WebSocket 连接,支持跨服务的长连接代理。
// 返回 *websocket.Conn
ws := d.Open("chat-service", "/stream")
5. 动态路由与负载管控
func (d *Discoverer) AddExternalApp(app, callConf string) bool: 在运行时动态添加一个新的下游依赖服务。func (d *Discoverer) SetNode(app, addr string, weight int): 手动硬编码设置节点信息(常用于本地 Mock 测试或灰度引流)。func (d *Discoverer) SetLoadBalancer(lb LoadBalancer): 自定义复杂负载均衡算法。func (d *Discoverer) SetRoute(route func(ac *AppClient, r *http.Request)): 设置请求的拦截/重写路由规则。
⚙️ Config 配置结构详解
作为 Start 和 Open 的最后一个可选参数:
type Config struct {
Weight int // 权重,默认为 100
Calls map[string]string // 提前声明调用的下游服务及其参数 (格式:超时时间:Token:H2C开关)
CallRetryTimes int // 请求单个下游节点的最大失败重试次数 (默认 10)
IpPrefix string // 在 EasyStart 模式下过滤并绑定指定网段的 IP
Logger *log.Logger // 自定义日志接口
}
环境变量 (EasyStart 模式)
仅在使用 discover.EasyStart()(自动探测本地 IP 和随机端口启动)时,支持以下环境变量:
DISCOVER_LISTEN: 本地试探监听的端口。
Description
Languages
Go
100%