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

httpcall

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package httpcall 提供可复用的 HTTP 下游客户端,统一记录调用日志与耗时。 它位于基础功能层,依赖 logit 和 Resty v2。

应用启动时通过 option 完成 Resty 配置,后续请求复用该实例和连接池; 以下初始化示例需导入 net/http、time、github.com/go-resty/resty/v2 和 github.com/bpcoder16/pixiu/infra/httpcall:

client := httpcall.New("inventory",
    httpcall.OptLogDetails(true), // 按需记录请求和响应的详细信息
    httpcall.OptPropagateLogID(true), // 按需向下游传递已有 logId
    httpcall.OptResty(func(r *resty.Client) {
        // 克隆默认 Transport,保留 Resty 的其他传输配置。
        transport := r.GetClient().Transport.(*http.Transport).Clone()
        transport.MaxIdleConns = 100 // 所有目标合计的空闲连接上限
        transport.MaxIdleConnsPerHost = 10 // 每目标空闲连接上限
        transport.MaxConnsPerHost = 50 // 每目标总连接上限,含拨号中、使用中和空闲连接
        transport.IdleConnTimeout = 90 * time.Second // 每条连接连续空闲多久后关闭
        r.SetTransport(transport)

        r.SetTimeout(90 * time.Second)
        r.SetBaseURL("https://inventory.example.com")
        r.SetRetryCount(2) // 最多重试 2 次,加上首次请求最多尝试 3 次
        r.SetRetryWaitTime(200 * time.Millisecond)
        r.SetRetryMaxWaitTime(time.Second)
        r.AddRetryCondition(func(resp *resty.Response, err error) bool {
            return resp != nil && resp.Request.Method == resty.MethodGet &&
                (err != nil || resp.StatusCode() == http.StatusTooManyRequests)
        })
    }),
)

省略 SetTimeout 时,每次 HTTP 尝试最长 60 秒。 连接池示例数值应按下游负载调整,所有上限按该客户端的 Transport 分别计算。 空闲连接上限不限制使用中的连接;达到每目标总连接上限时,新请求等待可用连接, 等待受请求 context 和客户端超时约束。空闲超时按每条连接单独计时。 示例只对 GET 的执行错误或 HTTP 429 重试,下面创建资源的 POST 不会自动重试; 需要重试 POST 时,应先确认下游具备幂等保障。

在请求处理函数中按接口设置截止时间。下面的函数需要导入 context、fmt、time 和 github.com/bpcoder16/pixiu/infra/httpcall:

func createItem(ctx context.Context, client *httpcall.Client, sku string) error {
    reqCtx, cancel := context.WithTimeout(ctx, 3*time.Second)
    defer cancel()
    resp, err := client.Request(reqCtx).
        SetHeader("Content-Type", "application/json").
        SetBody(map[string]string{"sku": sku}).
        Post("/items")
    if err != nil {
        return err
    }
    if resp.IsError() {
        return fmt.Errorf("inventory: HTTP %d", resp.StatusCode())
    }
    return nil
}

Request(ctx) 返回 Resty 请求,也可直接调用 Get、Put、Patch、Delete 等方法。 仅复用 Client;每次调用必须创建新 Request,每个 Request 只执行一次, 不得重复或并发执行,也不应改写 Attempt;同次执行内的自动重试由 Resty 管理。 HTTP 4xx/5xx 遵循 Resty 语义,不自动返回 Go error,业务应检查响应状态。 不配置 SetRetryCount 时默认不自动重试。OptResty 中可用 SetRetryCount、SetRetryWaitTime、 SetRetryMaxWaitTime 和 AddRetryCondition 配置重试次数、退避和条件。 OptResty 中的 SetTimeout(0) 可关闭客户端级上限,此时应通过请求 context 设置截止时间。 超时参数遵循 Resty 自身语义。OptResty 可在 New 时配置认证、重试和传输器等底层参数; nil 回调会 panic。自定义 Resty 事件回调也应在 OptResty 中注册;New 后通过 Resty() 追加回调,若回调 panic,可能使同一次调用产生两条结果日志。 公共认证和请求头可在 OptResty 中通过 SetAuthToken、SetHeader 设置; 仅针对单次调用的值应设置在 Request(ctx) 返回的请求上。 OptPropagateLogID 默认关闭;开启后从 context 的 meta 读取已有 logId, 经 TraceHeader(PIXIU-Log-Id)传给下游,与 ginx 的入口约定一致。 请求或客户端显式设置的同名 Header 优先,含空值,键名忽略大小写; 不生成 ID 或改写调用方的日志作用域,重试沿用请求 Header。 请求 context 可设置更短的截止时间,但不能放宽单次尝试的上限。 开启 Resty 重试后,整次调用可能超过单次尝试上限;需要总截止时间时为请求 context 设置超时。 每次调用通过 logit 记录统一的 downstream_type、downstream_duration_ms、 downstream_id 和 downstream_details;details 固定包含 method、attempt、url、status、err, 缺值时字符串为 ""、数字为 0;attempt 为实际尝试次数。 URL 优先取已构造的 RawRequest.URL,否则取 req.URL;不兼容同次调用的重试 URL 变更。 OptLogRequests 默认开启;设为 false 时不输出上述 HttpCall 结果日志, OptLogDetails 此时也不输出详细内容,Resty 自身的 stderr 诊断仍会保留。 ctx 已调用 logit.WithStart 时,每次 Execute 以 HttpCall_<name> 为前缀自动编号记录下游耗时, 即使关闭结果日志也不受影响,供业务调用 logit.InfoDuration 汇总;未调用 WithStart 时跳过。 首次尝试写入独立起点,包含业务前置回调和重试等待,继承 context 的新请求独立计时。 创建请求和预生成 curl 不启动计时;执行前被拒绝的无效请求或 SRV 解析错误记零耗时。 context 仅保存时间值,不引用 Request,也不维护完成后重置的状态。 OptLogDetails 默认关闭;开启后还会记录双方 Header、可读取的 Body、最终 URL、 响应状态文本、HTTP 协议和 Content-Length。不会读取业务接管的响应流;缺值用 空对象、空字符串或 0,未知的 Content-Length 保留 -1。详细内容不脱敏或截断, 可能包含凭据和大量数据,应保护日志存储与收集链路。 没有本轮响应的准备失败或 panic 使用当前请求 Header,不记录旧 RawRequest 的 Header 和 Body。 已有的 logit context 字段会随日志输出。 需要按请求分流结果日志时,可先用 logit.WithLoggerName(ctx, name) 设置请求 context; 非空名字使用已注册的命名 Logger,未注册或没有名字时使用默认 Logger。 Resty 自身的 Warnf/Errorf 另写入 stderr,带 httpcall、name 和级别,供进程日志收集器捕获; 重试期间可能产生多条诊断记录。Debugf 不输出;诊断信息不作脱敏。

Index

Constants

View Source
const TraceHeader = "PIXIU-Log-Id"

TraceHeader 是与 HTTP 服务入口约定一致的链路 ID 请求头。

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client 是可复用的 HTTP 下游客户端。运行期可以并发发请求,Resty 配置应在启动期完成。

func New

func New(name string, opts ...Option) *Client

New 创建下游客户端。默认每次 HTTP 尝试最长 60 秒,不自动重试。

func (*Client) Request

func (c *Client) Request(ctx context.Context) *resty.Request

Request 创建带调用方 context 的 Resty 请求。业务使用返回值的 Get/Post/Put 等方法。 每次调用必须创建新 Request;同一个 Request 不得重复或并发执行,自动重试由 Resty 管理。

func (*Client) Resty

func (c *Client) Resty() *resty.Client

Resty 返回底层客户端;自定义事件回调应通过 OptResty 在 New 内注册。 New 后追加事件回调不保证每次调用只记录一条结果日志。

type Option

type Option func(*Client)

Option 配置下游客户端,创建后不应在运行期并发修改配置。

func OptLogDetails

func OptLogDetails(enabled bool) Option

OptLogDetails 控制是否记录请求和响应的详细信息,默认关闭。 开启后会记录原始 Header 和可读取的 Body,不脱敏或截断。

func OptLogRequests

func OptLogRequests(enabled bool) Option

OptLogRequests 控制是否输出每次调用的 HttpCall 结果日志,默认开启。 关闭时仍记录请求级耗时,Resty 自身的 stderr 诊断不受影响。

func OptPropagateLogID

func OptPropagateLogID(enabled bool) Option

OptPropagateLogID 控制是否经 TraceHeader 传递 context 中已有的 logId,默认关闭。 请求或客户端已显式设置的同名 Header(含空值)优先;没有 logId 时不生成。

func OptResty

func OptResty(configure func(*resty.Client)) Option

OptResty 在 New 内配置底层 Resty 客户端;nil 回调会 panic。

Jump to

Keyboard shortcuts

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