封装通用http重试函数需支持灵活请求参数与可控重试策略:仅对网络错误(econnrefused等)和5xx服务端临时错误重试,采用指数退避+抖动等待,通过http_request_t结构体和http_perform_fn回调解耦执行逻辑。

封装一个通用的 HTTP 请求重试函数,核心是把“发请求 → 判断失败 → 等待 → 重试”这个逻辑抽离出来,同时保留原始请求的灵活性(比如支持不同方法、头、超时、重试次数等),而不是硬编码某个 URL 或业务逻辑。
明确重试触发条件
不是所有失败都该重试。通常只对以下情况做重试:
- 网络层错误:如连接超时、连接被拒、读写中断(errno 为 ECONNREFUSED、ETIMEDOUT、EHOSTUNREACH、EPIPE 等)
- HTTP 层临时性错误:状态码为 500、502、503、504(服务端暂时不可用)
- 避免重试:4xx 错误(如 400、401、404)一般代表客户端问题,重试无意义;3xx 重定向应由客户端自动跟随,不纳入重试逻辑
设计函数接口(C 语言风格)
推荐使用函数指针 + 参数结构体的方式,兼顾类型安全和扩展性:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 定义一个 http_request_t 结构体,包含 method、url、headers、body、timeout_ms、max_retries 等字段
- 定义回调函数类型 http_perform_fn:接收 request 结构体,返回 int(0=成功,-1=失败) 和填充好的 http_response_t*
- 主重试函数签名类似:int http_retry_perform(const http_request_t *req, http_perform_fn perform, http_response_t **out_resp)
实现重试控制逻辑
关键不是“多循环几次”,而是让每次重试有节奏、可退避:
- 用指数退避(exponential backoff):第 n 次重试前 sleep (2^n) + jitter 毫秒(例如 100ms、300ms、700ms…)
- 记录已重试次数,达到 max_retries 后直接退出
- 每次重试前检查是否还有时间余量(尤其当设了总超时 total_timeout_ms)
- 建议在日志中输出重试原因(如 “retry #1 after 503, waiting 100ms…”),方便调试
配合底层请求函数使用
你的实际 HTTP 发送函数(比如基于 socket 或 libcurl 封装的 http_do_get / http_do_post)只需专注单次执行,返回清晰的错误码和响应结构。重试函数不关心它内部怎么连、怎么解析,只依赖它的返回值做决策。例如:
- 调用 http_retry_perform(&req, http_do_post, &resp)
- 重试函数内部循环调用 http_do_post(&req, &resp),直到成功或耗尽重试次数
- 若某次调用返回 -1 且 errno 属于可重试范围,就等待后继续;否则立即返回错误
不复杂但容易忽略










