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

代理HttpHandler崩溃时异常捕获:如何重试或跳过失效代理

解决方案

问题分析

你的现有代码仅捕获了设置代理对象到HttpClientHandler这一步的异常,但实际代理失效的错误是在发送HTTP请求时抛出的,这部分逻辑未被包裹在异常捕获范围内,因此无法拦截目标错误。

修改方案

我们需要将HTTP请求逻辑纳入异常捕获范围,添加重试循环控制重试次数,捕获网络/代理相关的具体异常类型,最后在重试失败后跳过当前代理。

修改后的完整代码

private static async Task Check()
{
    // 配置最大重试次数
    const int maxRetryCount = 3;

    foreach (var cookieList in CookieList)
    {
        var user = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyuser");
        var pass = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxypass");
        var proxyIp = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyip");
        var proxyPort = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyport");
        
        bool proxySuccess = false;
        int retryCount = 0;

        while (retryCount < maxRetryCount && !proxySuccess)
        {
            retryCount++;
            HttpClient client = null;
            try
            {
                var container = new CookieContainer();
                var handler = new HttpClientHandler();
                handler.CookieContainer = container;
                
                WebProxy proxy = new WebProxy(proxyIp, Convert.ToInt32(proxyPort));
                if (user != null)
                {
                    proxy.Credentials = new NetworkCredential(user, pass);
                }
                handler.Proxy = proxy;

                client = new HttpClient(handler);
                client.BaseAddress = BaseAddress;

                // 替换为你的实际请求逻辑,比如GetAsync/PostAsync
                var response = await client.GetAsync("your-target-api-path");
                // 确保请求状态码正常,否则抛出HttpRequestException
                response.EnsureSuccessStatusCode();

                proxySuccess = true;
                LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 请求成功", Log.Type.Message);
            }
            // 捕获HttpClient请求异常(含代理连接失败、超时等)
            catch (HttpRequestException ex)
            {
                LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败: {ex.Message}", Log.Type.Message);
                // 重试前添加短暂延迟,避免频繁请求
                await Task.Delay(1000);
            }
            // 兼容旧版本的网络异常
            catch (WebException ex)
            {
                LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败(Web异常): {ex.Message}", Log.Type.Message);
                await Task.Delay(1000);
            }
            // 捕获底层连接异常
            catch (SocketException ex)
            {
                LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败(连接异常): {ex.Message}", Log.Type.Message);
                await Task.Delay(1000);
            }
            // 捕获其他意外异常,直接终止重试
            catch (Exception ex)
            {
                LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 发生未知错误: {ex.Message}", Log.Type.Message);
                break;
            }
            finally
            {
                // 释放HttpClient资源,避免内存泄漏
                client?.Dispose();
            }
        }

        if (!proxySuccess)
        {
            LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 重试{maxRetryCount}次均失败,已跳过", Log.Type.Message);
            // 跳过当前代理,进入下一个循环
            continue;
        }

        // 这里添加代理请求成功后的后续业务逻辑
    }
}

关键说明

  • 重试控制:通过maxRetryCount设定最大重试次数,用while循环实现重试逻辑
  • 精准捕获:针对性捕获HttpRequestException、WebException、SocketException,覆盖代理失效的常见场景
  • 资源管理:在finally块中释放HttpClient,避免资源泄漏
  • 延迟重试:每次失败后延迟1秒,避免对目标服务或代理造成过大压力
  • 跳过逻辑:重试全部失败后,用continue跳过当前代理,继续处理下一个任务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:30:45