# @go/discover > **Maintainer Statement:** 本项目完全由 AI 维护。任何改动均遵循代码质量与性能的最佳实践。 `@go/discover` 是一个**无状态、参数驱动**的极简服务发现与负载均衡组件。它基于 Redis 实现,专注于消除微服务调用间的摩擦,并原生支持 Header 链路透传。 ## 🎯 设计哲学 - **纯粹无状态 (Stateless)**:模块自身不读取配置文件,不依赖任何特定框架的上下文。它是一个纯粹的函数式库,配置的加载权力完全交给顶层(如 `@go/service`)。 - **面向对象隔离**:支持多实例共存。你可以在同一个进程中同时连接不同的注册中心,实现复杂的网关分发。 - **内存安全与高性能**:敏感令牌 (Token) 受 `@go/safe` 内存保护;调用耗时由 `@go/timer` 高性能打点引擎追踪;网络层支持 H2C (HTTP/2 Cleartext)。 ## 📦 安装 ```bash go get apigo.cc/go/discover ``` ## 💡 快速入门 (Quick Start) ### 1. 服务端模式 (Server) 如果你是一个需要被别人发现的服务,使用 `Start`。 ```go 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`。 ```go // 启动纯客户端 (注册中心地址, 可选配置) d := discover.Open("redis://127.0.0.1:6379/15") ``` --- ## 🛠 API Reference (实例方法) `Start` 和 `Open` 均会返回一个 `*discover.Discoverer` 实例,所有的业务调用都应通过此实例进行。 ### 1. 泛型快捷调用 (Stateless Data Fetching) 自动解析 JSON 响应到结构体,适用于绝大多数简单的 RPC 场景。 ```go 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)` 包装器可以极其优雅地实现。 ```go 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 状态码。 ```go res := d.Do("GET", "auth-service", "/verify", nil) if res.Error == nil { fmt.Println(res.String()) // 也可以: res.Save("file.txt") } ``` ### 4. WebSocket 支持 无缝升级为 WebSocket 连接,支持跨服务的长连接代理。 ```go // 返回 *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` 的最后一个可选参数: ```go 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`: 本地试探监听的端口。