2026-05-09 21:11:46 +08:00
|
|
|
|
# @go/discover
|
|
|
|
|
|
|
|
|
|
|
|
> **Maintainer Statement:** 本项目完全由 AI 维护。任何改动均遵循代码质量与性能的最佳实践。
|
|
|
|
|
|
|
|
|
|
|
|
`@go/discover` 是一个**无状态、参数驱动**的极简服务发现与负载均衡组件。它基于 Redis 实现,专注于消除微服务调用间的摩擦,并原生支持 Header 链路透传。
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 设计哲学
|
|
|
|
|
|
|
|
|
|
|
|
- **纯粹无状态 (Stateless)**:模块自身不读取配置文件,不依赖任何特定框架的上下文。配置加载由调用方负责,参数通过入口函数注入。
|
|
|
|
|
|
- **面向对象隔离**:支持多实例共存。可以在同一个进程中同时连接不同的注册中心。
|
|
|
|
|
|
- **内存安全与高性能**:访问令牌 (Token) 强制受 `@go/safe` 内存保护;调用耗时由 `@go/timer` 追踪;网络层支持 H2C。
|
|
|
|
|
|
|
|
|
|
|
|
## 📦 安装
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
go get apigo.cc/go/discover
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 💡 快速入门 (Quick Start)
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 服务端模式 (Server)
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
import "apigo.cc/go/discover"
|
|
|
|
|
|
|
|
|
|
|
|
// 可选配置
|
|
|
|
|
|
conf := discover.Config{
|
|
|
|
|
|
Weight: 100,
|
|
|
|
|
|
Calls: map[string]discover.CallConfig{
|
|
|
|
|
|
"auth-service": { Timeout: time.Second, Token: mySafeToken },
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 启动并注册 (注册中心地址, 我的服务名, 我的可访问地址, Logger, 可选配置)
|
|
|
|
|
|
d := discover.Start("redis://127.0.0.1:6379/15", "user-service", "198.18.0.1:8080", logger, conf)
|
|
|
|
|
|
defer d.Stop() // 优雅注销
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 纯客户端模式 (Client)
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
// 启动纯客户端 (注册中心地址, Logger, 可选配置)
|
|
|
|
|
|
d := discover.Open("redis://127.0.0.1:6379/15", logger, conf)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🛠 API Reference (实例方法)
|
|
|
|
|
|
|
|
|
|
|
|
`Start` 和 `Open` 均返回 `*discover.Discoverer` 实例。
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 服务间调用 (RPC)
|
|
|
|
|
|
返回 `*gohttp.Result`,结合 `go/http.To[T]` 实现结果绑定。
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
import "apigo.cc/go/http"
|
|
|
|
|
|
|
|
|
|
|
|
// 直接调用 (Get / Post / Put / Delete / Head / Do)
|
|
|
|
|
|
res := d.Get("user-service", "/api/info")
|
|
|
|
|
|
user, err := http.To[User](res)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 链路透传调用 (Context Propagation)
|
|
|
|
|
|
通过 `From(r)` 包装器提取原始请求上下文(TraceID, UserID 等)并向后透传。
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
func MyHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
// 自动透传上下文 Header
|
|
|
|
|
|
res := d.From(r).Post("user-service", "/create", reqData)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. WebSocket 支持
|
|
|
|
|
|
```go
|
|
|
|
|
|
// 返回 *websocket.Conn
|
|
|
|
|
|
ws := d.Open("chat-service", "/stream")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 动态管控
|
|
|
|
|
|
- `func (d *Discoverer) AddExternalApp(app string, conf CallConfig) bool`: 运行时添加下游依赖。
|
|
|
|
|
|
- `func (d *Discoverer) SetNode(app, addr string, weight int)`: 手动指定节点信息。
|
|
|
|
|
|
- `func (d *Discoverer) SetLoadBalancer(lb LoadBalancer)`: 自定义负载均衡算法。
|
|
|
|
|
|
- `func (d *Discoverer) SetRoute(route func(ac *AppClient, r *http.Request))`: 设置请求拦截/重写规则。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## ⚙️ Config 结构详解
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
type Config struct {
|
|
|
|
|
|
Weight int // 节点权重 (默认 100)
|
|
|
|
|
|
Calls map[string]CallConfig // 依赖服务的调用配置
|
|
|
|
|
|
CallRetryTimes int // 下游重试次数 (默认 10)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type CallConfig struct {
|
|
|
|
|
|
Timeout time.Duration // 超时时间
|
|
|
|
|
|
Token *safe.SafeBuf // 访问凭据 (强制安全存储)
|
|
|
|
|
|
Http2 bool // 强制 H2C/H2
|
|
|
|
|
|
SSL bool // 启用 SSL/WSS
|
|
|
|
|
|
}
|
2026-05-05 09:42:15 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-09 21:11:46 +08:00
|
|
|
|
## 注意事项
|
|
|
|
|
|
- `registry` 参数支持 Redis URL 或 `go/config` 下定义的 Redis 配置名称。
|
|
|
|
|
|
- `logger` 参数建议传入带有 TraceID 的实例以确保链路可追踪。
|