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

httpx

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Overview

Package httpx 提供 JSON HTTP 客户端。

所有 enjoydream 后端服务共享此包,统一 HTTP 调用方式。

核心特性

  • JSON 请求/响应自动序列化
  • Prometheus 指标采集
  • 熔断器(gobreaker)
  • 指数退避重试
  • OpenTelemetry 追踪
  • 文件上传(multipart/form-data)

快速接入

创建客户端:

client := ehttp.NewClient("user-service",
    ehttp.WithBaseURL("http://user-service:8080"),
    ehttp.WithTimeout(5*time.Second),
    ehttp.WithTracePropagation(),
)

GET 请求:

var users []User
err := client.GetJSON(ctx, "/api/users", &users)

POST 请求:

var result CreateUserResp
err := client.PostJSON(ctx, "/api/users", req, &result)

监控集成

使用 WithMetrics 启用 Prometheus 指标:

client := ehttp.NewClient("user-service",
    ehttp.WithMetrics(metrics.Registry, "myservice"),
)

指标包括(namespace 未显式指定时前缀为 http_client):

  • {ns}_requests_total{service, target, method, status_code}
  • {ns}_request_duration_seconds{service, target, method}
  • {ns}_requests_in_flight{service, target, method}

同一 Registry + namespace 下创建多个 Client 是安全的:同名指标自动复用 已注册的 collector。禁止 host/IP/port/path 等高基数 label。

熔断器

使用 WithCircuitBreaker 启用熔断保护:

client := ehttp.NewClient("user-service",
    ehttp.WithCircuitBreaker("user-service", gobreaker.Settings{
        MaxRequests: 3,
        Interval:    10 * time.Second,
        Timeout:     30 * time.Second,
    }),
)

熔断器状态变化会自动记录到日志。

错误处理

返回 ServiceError 类型,包含服务名、操作、状态码和响应体:

var svcErr *ehttp.ServiceError
if errors.As(err, &svcErr) {
    log.Printf("service: %s, action: %s, code: %d, message: %s",
        svcErr.Service, svcErr.Action, svcErr.Code, svcErr.Message)
}

Index

Constants

This section is empty.

Variables

View Source
var ErrCircuitOpen = breaker.ErrCircuitOpen

ErrCircuitOpen 表示熔断器处于打开状态,请求被拒绝。

规范哨兵定义于 concurrency/breaker(错误消息逐字为 "circuit breaker is open"), httpx 此处仅别名它:gobreaker 熔断路径与 adaptive 熔断器(concurrency/breaker) 拒绝时返回同一 sentinel,errors.Is 全链统一判定。判定一律用 errors.Is。

Functions

func WithPriority

func WithPriority(ctx context.Context, priority Priority) context.Context

WithPriority 将优先级注入 context。

Types

type BalanceStrategy

type BalanceStrategy interface {
	// Pick 从 endpoints 中选择一个。
	Pick(endpoints []string, req *http.Request) string
}

BalanceStrategy 负载均衡策略接口。

func NewBalanceAdapter

func NewBalanceAdapter(b loadbalance.Balancer) BalanceStrategy

NewBalanceAdapter 创建适配器,将 loadbalance.Balancer 包装为 httpx.BalanceStrategy。

type Client

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

Client 是封装了 Hertz HTTP 客户端的高层 HTTP 调用器,支持服务发现、负载均衡、熔断和指标。

func NewClient

func NewClient(service string, opts ...ClientOption) *Client

NewClient 创建 HTTP 客户端实例,应用指定的配置选项。

func (*Client) Close

func (c *Client) Close()

Close 关闭客户端,释放资源。

func (*Client) DoJSON

func (c *Client) DoJSON(ctx context.Context, method, path string, body any, out any) error

DoJSON 使用指定的 HTTP 方法发送请求。

func (*Client) DoRaw

func (c *Client) DoRaw(ctx context.Context, method, path string, body any) ([]byte, error)

DoRaw 使用指定的 HTTP 方法发送请求,返回原始响应字节数据。

func (*Client) GetJSON

func (c *Client) GetJSON(ctx context.Context, path string, out any) error

GetJSON 发送 GET 请求并将响应反序列化到 out。

func (*Client) Hertz

func (c *Client) Hertz() *client.Client

Hertz 返回底层 Hertz Client 实例,用于直接操作。

func (*Client) PostJSON

func (c *Client) PostJSON(ctx context.Context, path string, body any, out any) error

PostJSON 发送 POST 请求。

func (*Client) SetTarget

func (c *Client) SetTarget(target string)

SetTarget 运行时更新 target label。

func (*Client) UploadBytes

func (c *Client) UploadBytes(ctx context.Context, path string, data []byte, fieldName, fileName string, extraFields map[string]string, out any) error

UploadBytes 上传字节数据 (multipart/form-data)。

func (*Client) UploadFile

func (c *Client) UploadFile(ctx context.Context, path, filePath, fieldName string, extraFields map[string]string, out any) error

UploadFile 上传文件 (multipart/form-data)。

type ClientOption

type ClientOption func(*Client)

ClientOption 是 Client 的配置函数类型。

func WithBalance

func WithBalance(strategy BalanceStrategy) ClientOption

WithBalance 设置负载均衡策略。

func WithBaseURL

func WithBaseURL(u string) ClientOption

WithBaseURL 设置客户端的基础 URL。

func WithBasicAuth

func WithBasicAuth(user, password string) ClientOption

WithBasicAuth 为所有请求设置 Basic Auth 认证。

func WithBearerToken

func WithBearerToken(token string) ClientOption

WithBearerToken 为所有请求设置 Bearer Token 认证。

func WithCircuitBreaker

func WithCircuitBreaker(name string, settings gobreaker.Settings) ClientOption

WithCircuitBreaker 为客户端启用熔断器,使用指定的名称和配置。

func WithCookieJar

func WithCookieJar(jar http.CookieJar) ClientOption

WithCookieJar 为客户端设置 Cookie Jar。 Hertz client 不支持运行时设置 CookieJar;此选项记录警告并忽略。

func WithDebug

func WithDebug() ClientOption

WithDebug 开启调试日志。 Hertz client 不支持运行时调试开关(日志由 hlog 全局控制),此选项留作占位。

func WithEndpoints

func WithEndpoints(endpoints ...string) ClientOption

WithEndpoints 设置静态 endpoint 列表。

func WithMetrics

func WithMetrics(registry prom.Registerer, namespace string) ClientOption

WithMetrics 为客户端启用 Prometheus 指标采集。

func WithNNS

func WithNNS(serviceName string, nnsClient NNSClient) ClientOption

WithNNS 启用 NNS 服务发现。

func WithOnBeforeRequest

func WithOnBeforeRequest(fn func(ctx context.Context, req *protocol.Request) error) ClientOption

WithOnBeforeRequest 注册请求前置钩子。 ⚠️ Breaking: 签名从 func(*req.Client, *req.Request) 改为 func(ctx context.Context, req *protocol.Request)(hertz protocol 类型)。

func WithPriorityQueue

func WithPriorityQueue(capacity int) ClientOption

WithPriorityQueue 启用请求优先级队列。

func WithRefreshInterval

func WithRefreshInterval(d time.Duration) ClientOption

WithRefreshInterval 设置 endpoint 刷新间隔。

func WithRetryConfig

func WithRetryConfig(maxAttempts uint, initDelay, maxDelay, maxJitter time.Duration) ClientOption

WithRetryConfig 配置请求重试策略,走 Hertz 官方 client.WithRetryConfig。 参数语义:

  • maxAttempts:总尝试次数(>=1,含首次请求);0 = 走 Hertz 默认 1 次
  • initDelay:首次重试前的等待时间(指数退避基数,对应 retry.Config.Delay)
  • maxDelay:重试延迟上限(避免退避无界增长,retry.Delay 内部封顶)
  • maxJitter:随机抖动上限(避免雪崩,对应 retry.Config.MaxJitter)

DelayPolicy 必须显式设置:hertz WithRetryConfig 的默认 DelayPolicy 是 retry.DefaultDelayPolicy(恒返回 0,参见 hertz pkg/app/client/retry/retry.go), 不设置的话 initDelay/maxDelay/maxJitter 三个参数全部无效、重试零等待。 ekit 固定注入 CombineDelay(BackOffDelayPolicy, RandomDelayPolicy): 每次重试延迟 = initDelay<<attempts + [0, maxJitter) 随机抖动,MaxDelay 封顶。

⚠️ 重试触发条件(与 Hertz 默认不同):

Hertz 官方 DefaultRetryIf 仅在网络错误时重试,不重试 5xx 响应(只检查
idempotent 方法 — 参见 vendor 源码 protocol/client/client.go:82)。
ekit WithRetryConfig 默认同时重试 5xx + network error,语义对齐旧
WithRetry(手写 middleware) 行为。如果需要更严格的条件(例如只重试
GET/HEAD/OPTIONS/TRACE/特定状态码),可通过 WithRetryIfFunc 覆盖。

官方依据:https://www.cloudwego.io/zh/docs/hertz/tutorials/basic-feature/client/ (Client 配置表 WithRetryConfig 示例明确列出 retry.WithDelayPolicy; 退避/抖动语义见 hertz pkg/app/client/retry 包:BackOffDelayPolicy = Delay<<attempts, RandomDelayPolicy = fastrand.Int63n(MaxJitter),CombineDelay 求和)

用法:

cli := httpx.NewClient("my-svc",
    httpx.WithRetryConfig(3, 100*time.Millisecond, 1*time.Second, 50*time.Millisecond),
)

func WithRetryIfFunc

func WithRetryIfFunc(fn func(req *protocol.Request, resp *protocol.Response, err error) bool) ClientOption

WithRetryIfFunc 覆盖 ekit 默认重试触发条件(5xx + network error), 由用户传更严格的 predicate(例如只对 GET 重试、特定状态码范围等)。 不调 WithRetryIfFunc 时,WithRetryConfig 注入默认 5xx + network error 条件。

func WithServiceResolver

func WithServiceResolver(resolver ServiceResolver) ClientOption

WithServiceResolver 设置自定义服务发现解析器。

func WithTLSSkipVerify

func WithTLSSkipVerify() ClientOption

WithTLSSkipVerify 跳过 TLS 证书验证。

func WithTarget

func WithTarget(target string) ClientOption

WithTarget 设置指标 target label 的值。

func WithTimeout

func WithTimeout(d time.Duration) ClientOption

WithTimeout 设置 HTTP 请求超时时间。

func WithTracePropagation

func WithTracePropagation() ClientOption

WithTracePropagation 启用 OpenTelemetry 上下文透传(traceparent / tracestate / baggage), 走 Hertz client.UseAsLast 注入,在所有自定义中间件之后执行,

避免 trace 头被其他中间件覆盖或重复。

propagator 通过 otel.GetTextMapPropagator() 读取(默认 W3C TraceContext + Baggage), 与 ekit observability/tracing 全局配置保持一致 — 调用方只需先初始化 tracer + propagator。

官方依据:https://www.cloudwego.io/zh/docs/hertz/tutorials/basic-feature/client/ (UseAsLast 章节:"中间件设置在 ctx.lastMiddleware 中,使用 Use 设置的中间件链存放在 ctx.mws 中,两者相对独立,只是在执行客户端中间件链的最后才执行 ctx.lastMiddleware")

type ConsistentHashBalance added in v0.2.0

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

ConsistentHashBalance 一致性哈希负载均衡:同一 key 稳定路由到同一 endpoint, endpoint 增减仅引起相邻键的重新映射(对比 HashBalance 的全量重排)。 适合有状态粘滞路由(同用户/同租户粘住同实例)且实例列表动态变化的场景。

key 缺省取请求路径(可用 WithConsistentKeyFunc 定制,如同租户取 header); 实现了 WeightedBalanceStrategy——resolver 提供实例权重时按权重折算各节点 虚拟副本数,注册中心权重配置照常生效。

func NewConsistentHashBalance added in v0.2.0

func NewConsistentHashBalance(opts ...ConsistentHashOption) *ConsistentHashBalance

NewConsistentHashBalance 创建一致性哈希负载均衡策略。

func (*ConsistentHashBalance) Pick added in v0.2.0

func (b *ConsistentHashBalance) Pick(endpoints []string, req *http.Request) string

Pick 按一致性哈希选择 endpoint。

func (*ConsistentHashBalance) SetWeights added in v0.2.0

func (b *ConsistentHashBalance) SetWeights(weights []float64)

SetWeights 更新实例权重(WeightedBalanceStrategy 实现):权重按比例折算 各节点虚拟副本数(等权均值归一),下次 Pick 触发重建环。

type ConsistentHashOption added in v0.2.0

type ConsistentHashOption func(*ConsistentHashBalance)

ConsistentHashOption ConsistentHashBalance 的可选参数。

func WithConsistentHashFunc added in v0.2.0

func WithConsistentHashFunc(fn func([]byte) uint64) ConsistentHashOption

WithConsistentHashFunc 自定义哈希函数(默认 FNV-1a 64)。nil 被忽略。

func WithConsistentKeyFunc added in v0.2.0

func WithConsistentKeyFunc(fn func(req *http.Request) string) ConsistentHashOption

WithConsistentKeyFunc 自定义路由 key 提取(默认请求路径)。nil 被忽略。 key 语义由业务保证(如同租户取 header 值);恒为空的 key 会把全部请求 路由到同一节点。

func WithConsistentReplicas added in v0.2.0

func WithConsistentReplicas(n int) ConsistentHashOption

WithConsistentReplicas 设置每个 endpoint 的虚拟副本数(默认 100)。 n <= 0 被忽略。

type EndpointManager

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

EndpointManager endpoint 管理器。 支持静态配置、动态刷新、缓存降级。

func NewEndpointManager

func NewEndpointManager(resolver ServiceResolver, balance BalanceStrategy, refreshInterval time.Duration) *EndpointManager

NewEndpointManager 创建 endpoint 管理器。

func (*EndpointManager) GetEndpoints

func (m *EndpointManager) GetEndpoints() []string

GetEndpoints 获取 endpoint 列表(优先使用最新,降级使用缓存)。

func (*EndpointManager) Pick

func (m *EndpointManager) Pick(req *http.Request) string

Pick 选择一个 endpoint。

func (*EndpointManager) SetEndpoints

func (m *EndpointManager) SetEndpoints(endpoints []string)

SetEndpoints 设置静态 endpoint 列表。

func (*EndpointManager) Stop

func (m *EndpointManager) Stop()

Stop 停止刷新。

type HashBalance

type HashBalance struct{}

HashBalance 哈希负载均衡(基于请求路径 CRC32)。

func (*HashBalance) Pick

func (b *HashBalance) Pick(endpoints []string, req *http.Request) string

Pick 基于请求路径 CRC32 哈希选择 endpoint(同一路径总是路由到同一节点)。

type NNSClient

type NNSClient interface {
	GetInstances(ctx context.Context, serviceName string) ([]registry.Instance, error)
}

NNSClient NNS 客户端接口,与顶层 nns.NNSClient.GetInstances 签名一致。

type NNSResolver

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

NNSResolver NNS 服务发现解析器。

func NewNNSResolver

func NewNNSResolver(serviceName string, nnsClient NNSClient) *NNSResolver

NewNNSResolver 创建 NNS 解析器。

func (*NNSResolver) Resolve

func (r *NNSResolver) Resolve(ctx context.Context) ([]string, error)

Resolve 解析服务名称,返回可用的 endpoint 列表(丢弃权重)。

func (*NNSResolver) ResolveWeighted

func (r *NNSResolver) ResolveWeighted(ctx context.Context) ([]WeightedEndpoint, error)

ResolveWeighted 解析服务名称,返回带实例权重的 endpoint 列表。 权重来自注册中心(registry.Instance.Weight),使加权 LB 策略在 httpx 路径上生效;透传 context 到 NNS,保留超时和 trace_id 语义。

type Priority

type Priority int

Priority 请求优先级。

const (
	PriorityLow    Priority = 0
	PriorityNormal Priority = 1
	PriorityHigh   Priority = 2
)

func GetPriority

func GetPriority(ctx context.Context) Priority

GetPriority 从 context 获取优先级。

type PriorityQueue

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

PriorityQueue 分级准入控制队列。

注意语义:这是分级准入控制而非严格优先级队列——high/normal/low 三级 各自独立计数(同级 FIFO),不保证跨级抢占;高优先级请求不会抢占已获准的 低优先级请求,仅在自身级别容量内准入。未知优先级按 PriorityNormal 处理。

func NewPriorityQueue

func NewPriorityQueue(capacity int) *PriorityQueue

NewPriorityQueue 创建优先级队列。

func (*PriorityQueue) Acquire

func (q *PriorityQueue) Acquire(ctx context.Context, priority Priority) bool

Acquire 获取许可(按优先级)。

func (*PriorityQueue) Len

func (q *PriorityQueue) Len() int

Len 返回队列长度。

func (*PriorityQueue) Release

func (q *PriorityQueue) Release(priority Priority)

Release 释放许可。

priority 必须与 Acquire 时一致;未知优先级按 PriorityNormal 释放 (与 Acquire 的 default 分支对齐),避免静默泄漏许可。

type ServiceError

type ServiceError struct {
	Service string
	Action  string
	Code    int
	Message string
}

ServiceError 表示 HTTP 服务调用返回的业务错误。

func (*ServiceError) Error

func (e *ServiceError) Error() string

Error 实现 error 接口,返回格式化的错误信息。

type ServiceResolver

type ServiceResolver interface {
	// Resolve 解析服务名称,返回可用的 endpoint 列表。
	Resolve(ctx context.Context) ([]string, error)
}

ServiceResolver 服务发现解析器接口。

type StaticResolver

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

StaticResolver 静态 endpoint 解析器。

func NewStaticResolver

func NewStaticResolver(endpoints []string) *StaticResolver

NewStaticResolver 创建静态解析器。

func (*StaticResolver) Resolve

func (r *StaticResolver) Resolve(ctx context.Context) ([]string, error)

Resolve 返回静态配置的 endpoint 列表。

type WeightedBalanceStrategy

type WeightedBalanceStrategy interface {
	BalanceStrategy
	SetWeights(weights []float64)
}

WeightedBalanceStrategy 是 BalanceStrategy 的可选增强接口: 接受实例权重分布的策略。仅对经 NewBalanceAdapter 适配 network/loadbalance.Balancer 的策略生效;自定义 BalanceStrategy 实现不感知权重(等权语义)。

type WeightedEndpoint

type WeightedEndpoint struct {
	Addr   string
	Weight float64
}

WeightedEndpoint 带权重的 endpoint 视图。 Weight 为实例注册权重(<=0 由负载均衡策略按 1 处理),0 值在 注册中心未提供权重时与等权语义等价。

type WeightedResolver

type WeightedResolver interface {
	// ResolveWeighted 解析服务名称,返回带权重的 endpoint 列表。
	ResolveWeighted(ctx context.Context) ([]WeightedEndpoint, error)
}

WeightedResolver 是 ServiceResolver 的可选增强接口:提供带实例权重的 endpoint 视图。EndpointManager 检测到 resolver 实现本接口时,会把真实 权重喂给支持权重的负载均衡策略(见 WeightedBalanceStrategy); 仅实现 ServiceResolver 的 resolver 保持等权语义(历史行为)。

Jump to

Keyboard shortcuts

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