Help us shape the future of Go! Take the 2026 Go Developer Survey

client

package
v2.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CONTENT_TYPE_FORM    = "x-form"
	CONTENT_TYPE_JSON    = "json"
	CONTENT_TYPE_RESTFUL = "restful"
	CONTENT_TYPE_FILE    = "file"
)

Variables

View Source
var (
	// ErrCircuitOpen 熔断器处于打开状态,请求被快速失败(未真正发起调用)。
	ErrCircuitOpen = errors.New("client: 熔断器已打开,请求被快速失败")
	// ErrCallTimeout 调用超过 ResilienceOptions.Timeout 仍未返回。
	ErrCallTimeout = errors.New("client: 微服务调用超时")
)

调用级韧性策略的错误哨兵,便于调用方用 errors.Is 判断。

View Source
var ErrAllInstancesCircuitOpen = errors.New("client: all instances circuit-open")

ErrAllInstancesCircuitOpen v2 负载均衡专用错误:当服务的全部实例都被熔断时返此错误, 调用方可以快速失败(避免对已挂掉的下游继续施压)。

Functions

func Call

func Call(service, uri string, op *Options) (string, error)

Call 是 v1 时代的微服务调用入口,等价于 CallCtx(context.Background(), service, uri, op)。 保留以兼容存量项目;新代码建议直接使用 CallCtx 以便传入 context(例如超时/取消)。

func CallCtx

func CallCtx(ctx context.Context, service, uri string, op *Options) (string, error)

CallCtx 是 v2 新增的"支持 context"版本微服务调用入口。

背景:v1 的 Call 不支持 context,导致:

  • 无法把 ctx 透传到 grequests 底层(grequests 的 DoRegularRequest 不接受 ctx)
  • 业务侧无法用 ctx 实现超时或链路取消

v2 决策(已与用户确认):**保持 goroutine+timer 兑底**, 即调用方在 CallCtx 内部通过 ctx 控制的超时计时器来"及时返回",但底层 HTTP 请求 不会被真正取消,仍会占用连接到对端响应或连接超时。要做到真正取消需要升级 `levigross/grequests` 或换 net/http 自封装,那是 v2.1+ 的工作。

ctx 在本函数的作用:

  • 通过 grequests 兼容的 RequestOptions 携带(未来 SDK 支持时直接生效)
  • 用于超时/取消的"上层兜底"(业务可在外层用 select 控制)
  • 链路 trace header 由 trace.GetHeaders() 透传,与 ctx 无关

func CallCtxT

func CallCtxT[T any](ctx context.Context, service, uri string, op *Options) models.Result[T]

CallCtxT 是 CallT 的 context 版本,语义对齐 CallCtx。

func CallResilient

func CallResilient(service, uri string, op *Options, ro *ResilienceOptions) (string, error)

CallResilient 在 client.Call 之上叠加超时、指数退避(带 jitter)重试与熔断。

幂等性保护(非常重要):

  • 幂等读(GET / HEAD / OPTIONS / TRACE)默认可重试;
  • 非幂等写(POST / PUT / DELETE / PATCH)默认不重试,避免重复下单、重复扣款等副作用;
  • 唯一例外:调用方显式提供 RetryOnStatus,且从错误中解析出的状态码被该回调判定为可重试;
  • Options.Method 为空时,按 client.Call 的既有默认值视为 POST(非幂等,默认不重试)。

默认安全:ro 为 nil 或其所有字段为零值时,等价于直接调用一次 client.Call (不重试、不超时、不熔断),既有调用方不受任何影响。

参数:

  • service: 微服务名。
  • uri: 接口路径。
  • op: 调用参数,与原 client.Call 一致;函数不会修改调用方传入的 op。
  • ro: 韧性策略,可为 nil。

返回值:

  • string: 成功时返回响应体,与原 client.Call 一致。
  • error: 失败时返回最后一次的错误;熔断打开时返回包装了 ErrCircuitOpen 的错误。

CallResilient 是 Call 的"带韧性策略"版本,等价于 CallResilientCtx(context.Background(), service, uri, op, ro)。 保留以兼容 v1 时代使用 CallResilient 的项目。

func CallResilientCtx

func CallResilientCtx(ctx context.Context, service, uri string, op *Options, ro *ResilienceOptions) (string, error)

CallResilientCtx 是 CallResilient 的 context 版本(v2 新增)。

与 CallResilient 的差异:把 context 透传到 callWithTimeout 的 goroutine 调用链, 调用方可在 ctx 中带超时或取消信号。需要 ctx 真正取消底层 HTTP 时, 当前实现是"goroutine+timer 兑底"(见 v2-design §6.2),不依赖 grequests 升级。

func CallT

func CallT[T any](service, uri string, op *Options) models.Result[T]

func ResetBreakers

func ResetBreakers()

ResetBreakers 清空全局熔断器注册表,主要用于测试场景。

Types

type CircuitBreaker

type CircuitBreaker struct {
	// contains filtered or unexported fields
}

CircuitBreaker 一个轻量三态熔断器。

采用纯标准库实现(sync/atomic 未使用,统一用互斥锁保护状态), 不引入 gobreaker / hystrix 等第三方依赖,避免给框架增加依赖负担。

计数模型:固定窗口计数(窗口长度 interval),窗口到期或发生状态跳转时清零重新计数。 该模型足够覆盖微服务调用保护场景,且实现简单、无额外内存开销。

func GetBreaker

func GetBreaker(name string) *CircuitBreaker

GetBreaker 按名称获取(或首次创建)一个全局共享的熔断器。 未显式指定参数时使用默认阈值:60 秒窗口内失败 5 次即熔断,冷却 30 秒后半开探测。 需要自定义参数时请使用 NewCircuitBreaker 并把结果赋给 ResilienceOptions.Breaker。

func NewCircuitBreaker

func NewCircuitBreaker(name string, maxFailures int, interval, timeout time.Duration) *CircuitBreaker

NewCircuitBreaker 创建一个熔断器。 参数:

  • name: 熔断器名称,用于日志与 String()。
  • maxFailures: 计数窗口内失败次数阈值,<=0 时使用 defaultMaxFailures。
  • interval: 失败计数窗口长度,<=0 时使用 defaultBreakerInterval。
  • timeout: 熔断打开后的冷却时长,<=0 时使用 defaultBreakerTimeout。

func (*CircuitBreaker) Allow

func (cb *CircuitBreaker) Allow() bool

Allow 判断当前请求是否允许放行。 熔断打开且未到冷却时间时返回 false(快速失败);冷却时间到达时会自动切换到半开并放行探测请求。 一旦 Allow 返回 true,调用方必须在请求结束后调用 Success() 或 Failure() 归还半开配额。

func (*CircuitBreaker) Counts

func (cb *CircuitBreaker) Counts() (failures int, successes int)

Counts 返回当前计数窗口内的失败次数与成功次数。

func (*CircuitBreaker) Failure

func (cb *CircuitBreaker) Failure()

Failure 上报一次失败结果。

func (*CircuitBreaker) Name

func (cb *CircuitBreaker) Name() string

Name 返回熔断器名称。

func (*CircuitBreaker) Reset

func (cb *CircuitBreaker) Reset()

Reset 强制把熔断器恢复到关闭状态并清零计数。

func (*CircuitBreaker) State

func (cb *CircuitBreaker) State() State

State 返回熔断器当前状态。

func (*CircuitBreaker) String

func (cb *CircuitBreaker) String() string

String 返回熔断器的可读描述,用于错误信息与日志。

func (*CircuitBreaker) Success

func (cb *CircuitBreaker) Success()

Success 上报一次成功结果。

type Options

type Options struct {
	Method   string                 `json:"method"`   //接口方法 GET|POST|PUT|DELETE
	Protocol string                 `json:"protocol"` //协议 x-form|json|restful
	Group    string                 `json:"group"`    //应用分组,用于nacos中分组,不传为当前nacos分组及默认分组
	Header   any                    `json:"header"`   //额外的头部参数
	Query    any                    `json:"query"`    //URL Query参数
	Data     any                    `json:"data"`     //x-form Postform参数
	Json     any                    `json:"json"`     //json或restful模式的body参数
	Path     map[string]string      `json:"path"`     //restful模式的路径参数
	Files    []grequests.FileUpload //文件上传数据
	Retry    bool                   `json:"retry"` //是否重试

	// v2 新增:负载均衡相关字段(可选,零侵入)。
	// LoadBalancer 为空时走 loadbalancer.Default()(RoundRobin)。
	// 命名常量参见 pkg/loadbalancer:roundrobin / random / leastconn / consistenthash。
	LoadBalancer string `json:"loadbalancer,omitempty"`
}

type ResilienceOptions

type ResilienceOptions struct {
	// Timeout 单次调用的超时时间。<=0 表示不启用超时(与现有行为一致)。
	Timeout time.Duration
	// MaxRetries 除首次调用外最多重试的次数。<=0 表示不重试(与现有行为一致)。
	MaxRetries int
	// BaseDelay 指数退避的初始延迟,<=0 时使用 defaultBaseDelay(100ms)。
	BaseDelay time.Duration
	// MaxDelay 指数退避的延迟上限,<=0 时使用 defaultMaxDelay(2s)。
	MaxDelay time.Duration
	// RetryOnStatus 判定哪些 HTTP 状态码可重试。
	//
	// 【重要限制】现有 client.Call 的返回值只有响应体字符串与 error:
	// 非 2xx 响应(如 500/503)在 grequests 层面并不算 error,会以正常响应体返回,
	// 因此通过 CallResilient 调用时通常拿不到状态码,本回调也就不会被触发。
	// 只有当错误文本中出现形如 "status code 503" / "HTTP 500" / "code=502" 的
	// 状态码信息时(自定义错误、网关错误、未来 Call 返回带状态码的错误)才会生效。
	// 解析失败时回退到下面的幂等性默认策略。
	// 若后续允许为 Options 增加可选的状态码输出字段,本回调即可完整生效。
	RetryOnStatus func(code int) bool
	// Breaker 熔断器,nil 表示不启用熔断。可用 client.GetBreaker(service) 获取全局共享实例。
	Breaker *CircuitBreaker
}

ResilienceOptions 描述在 client.Call 之外叠加的韧性策略。 所有字段都是可选的;零值 / nil 表示“不使用该能力”,行为与直接调用 client.Call 完全一致。

type State

type State int

State 表示熔断器当前所处的状态。

const (
	StateClosed State = iota
	StateHalfOpen
	StateOpen
)

熔断器三态:

Closed   —— 关闭(正常):请求正常放行,失败计数达到阈值后跳转 Open
Open     —— 打开(熔断):请求被快速失败,冷却时间到达后跳转 HalfOpen
HalfOpen —— 半开(探测):放行少量请求做探测,成功则回到 Closed,失败则立刻回到 Open

func (State) String

func (s State) String() string

String 返回状态的中文名,便于日志阅读。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL