You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Libcurl multi重试机制仅重试1次跳过后续请求问题如何解决

问题核心原因

  1. 失败请求的handle未重置重加,无法发起二次请求
    当前逻辑仅将返回200的easy handle从multi实例中移除,失败的handle会一直留在multi实例中。libcurl中完成过一次请求的easy handle,除非先移除再重新添加、或重置状态,否则不会重复发起请求,第二次进入loop执行curl_multi_perform时会直接判定所有任务已完成,不会发起新的请求。

  2. 二次执行无完成消息,rerun未被赋值导致重试中断
    每次进入消息处理逻辑前,rerun都会被初始化为0。第二次执行时没有新的请求完成,curl_multi_info_read直接返回NULL,消息处理循环完全不执行,rerun保持0值,自然不会触发下一次重试。

修复方案

处理完成消息时无论成功失败,都先将对应easy handle从multi实例移除,维护失败请求列表,重试前重置失败handle的状态、重新设置请求参数,再加回multi实例即可。
参考修改后的核心代码逻辑:

CURL* array[] = {
    curl_easy_init(),
    curl_easy_init(),
    curl_easy_init()
};
CURLM* multi = curl_multi_init();
// 提前存好所有请求的URL,方便重试时设置
const char* urls[] = {
    "https://www.example.com/",
    "https://www.example.com/",
    "https://americas.api.riotgames.com/riot/account/v1/accounts/by-puuid/Dxon1TsoGLOAvUykGYErrEPAT_U9YkQ_jNFZpRxYpfRFwnaYVFULVshNQnZapa4qR_pe5sSBn5MQvw"
};

for (int i = 0; i < 3; i++) {
    curl_easy_setopt(array[i], CURLOPT_URL, urls[i]);
    curl_multi_add_handle(multi, array[i]);
}
int retry = 3;
loop:
int run = 1;
while (run) {
    CURLMcode mc = curl_multi_perform(multi, &run);
    if (mc == CURLM_OK) {
        mc = curl_multi_poll(multi, NULL, 0, 0, NULL);
    }
    if (mc != CURLM_OK) {
        exit(0);
    }
}
CURLMsg *msg;
long rerun = 0;
int msgNum = 0;
int failed[3] = {0}; // 标记失败的请求下标
while (msg = curl_multi_info_read(multi, &msgNum)) {
    if (msg->msg == CURLMSG_DONE) {
        if (msg->data.result != CURLE_OK) {
            puts("ERROR");
            exit(0);
        }
        long httpCode;
        curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &httpCode);
        // 无论成功失败先移除handle
        curl_multi_remove_handle(multi, msg->easy_handle);
        if (httpCode == 200) {
            // 成功请求直接处理响应即可
        } else {
            rerun = httpCode;
            printf("\nError : %d\n", rerun);
            // 标记对应下标为失败
            for (int i = 0; i < 3; i++) {
                if (array[i] == msg->easy_handle) {
                    failed[i] = 1;
                    break;
                }
            }
        }
    } else {
        puts("ERROR");
        exit(0);
    }
}
puts("NExt");
if (rerun && --retry) {
    printf("%d - %d\n", retry, rerun);
    Sleep(1000);
    // 把失败的handle重置参数后重新加回multi
    for (int i = 0; i < 3; i++) {
        if (failed[i]) {
            curl_easy_reset(array[i]);
            curl_easy_setopt(array[i], CURLOPT_URL, urls[i]);
            // 其他需要设置的参数(比如header、超时等)也在这里重新设置
            curl_multi_add_handle(multi, array[i]);
        }
    }
    goto loop;
}
// 最后统一清理handle和multi实例
for (int i = 0; i < 3; i++) {
    curl_easy_cleanup(array[i]);
}
curl_multi_cleanup(multi);
puts("Finisheed");
exit(0);

额外说明:示例中返回的401是授权错误,说明请求缺少有效身份凭证,这类错误重试不会生效,仅服务端5xx错误、网络超时等场景重试才有意义。


内容的提问来源于stack exchange,提问作者LardPies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:24:04