Java 爬虫代理在高并发采集场景下,连接池与重试机制应该如何设计

高并发采集里,代理并不是“多加几条IP就能跑得更快”,真正决定稳定性的通常是两件事:连接池有没有把连接复用、超时、并发上限管理好;重试机制有没有把可恢复错误和不可恢复错误区分开,并且做到限流、退避、熔断、隔离。否则就会出现典型事故:线程数越开越多、连接越建越慢、代理被打穿、目标站点误判为攻击、最终全链路雪崩。

下面用工程化方式讲清楚:Java 侧连接池怎么设计,代理池怎么接入,重试怎么写才能既稳又不把问题放大。默认前提是合规采集,遵守站点政策与访问频率限制。

一、先把采集链路拆清楚,别把连接池当万能加速器

1、三层并发要分别限

高并发系统里至少存在三层并发:业务并发、HTTP并发、代理并发。很多人只加线程数,没给后两层设上限,结果是线程挤爆连接池,连接池挤爆代理,代理再挤爆目标站点。正确做法是三层都要有硬上限,并且上限之间要匹配。

建议用一个简单心法:先定“代理池总QPS”,再反推连接池并发,再反推任务并发。不要反过来用线程数去碰运气。

2、把请求类型分级

重试策略必须依赖请求类型:幂等请求如 GET、HEAD、可安全重放的查询;非幂等请求如写入、触发操作、某些换票据流程。非幂等默认不要自动重试,除非你有幂等键或去重机制,否则一次抖动会直接造成重复写入或异常状态。

二、连接池设计要点,目标是复用、控并发、控超时

1、选型与参数,先把“借连接”这件事管住

Apache HttpClient 4/5 适合复杂池化与路由控制,OkHttp 易用但需要额外封装“按代理限流”。无论选型,核心参数思路一致:

  • maxTotal:连接池全局最大连接数
  • maxPerRoute:单路由最大连接数,建议按代理出口维度拆
  • connectTimeout:连接建立超时
  • read/responseTimeout:响应读取超时
  • connectionRequestTimeout:从池里借连接的等待时间

经验上,高并发不是把 maxTotal 开到天上,而是让连接数略大于稳定并发,再用队列与限流控制吞吐。连接数越大,抖动时放大效应越强。

2、Keep-Alive 与空闲回收,吞吐主要来自复用

高并发吞吐很大一部分来自连接复用。建议:

  • 默认启用 keep-alive
  • 定期回收 idle 连接,避免半开连接堆积
  • 设置连接 TTL,避免连接太老出现诡异失败

代理出口对长连接稳定性差异很大,把最大空闲时间设短一点、并让清理任务持续运行,往往比无限复用更稳。

3、按代理做隔离,别让一个坏出口污染全局

如果你动态切代理,但连接池只按目标 host 做路由,不同代理的连接会混在一起:坏代理导致大量失败与重试污染全局池;也无法对单代理并发做硬限制。更稳做法是把代理出口作为隔离维度之一:每个代理都要有自己的并发上限、失败统计与熔断状态。连接池做不到就业务层用“每代理信号量”限并发。

三、重试机制设计,核心是分类、退避、预算、熔断

1、把错误分四类,别一股脑重试

建议至少分四类:

  • 连接类错误:连接超时、拒绝、TLS失败、隧道失败
  • 读写超时:read/response timeout
  • 站点限流:429、503,或响应头提示
  • 不可恢复:多数 4xx(除 429),以及明确业务错误

策略建议:

  • 连接类:小次数重试,快速切换代理或降级
  • 读写超时:优先降并发或延长超时,避免盲目重试放大
  • 限流类:必须退避、降速、甚至暂停该域名或该代理一段时间
  • 不可恢复:默认不重试,直接记录与告警

2、指数退避要带抖动,避免重试风暴

高并发最怕齐步重试。退避建议:指数退避 base * 2^n,加 0–30% 抖动,设置最大退避上限。这样才能把重试时刻打散,避免把一次短抖动放大成持续雪崩。

3、重试要有总预算,允许失败但不允许失控

建议两层预算:

  • 单请求最大重试 2–3 次
  • 单域名或单任务每分钟重试额度,超额直接熔断或降速

否则你会看到失败越多重试越多、重试越多失败越多的自激振荡。

4、熔断与半开恢复,把坏代理自动隔离

每个代理出口维护健康状态:连续失败到阈值就熔断,冷却后半开少量探测,成功再恢复;同时用成功率与延迟评分动态调权。这套机制既保护代理池,也保护目标站点,能显著降低被封或被限流的概率。

四、代理池接入方式,重点是分池与健康评分

1、不要把所有任务混用同一代理池

高并发采集至少分两类池:采集池承受高频请求,强调隔离与可控并发;账号或登录池承受低频敏感请求,强调稳定与低波动。两类混用最容易连坐:采集把出口打废,账号一起出问题。

2、最小健康闭环,先把“坏出口”识别出来

每个代理维护:窗口成功率、平均延迟、超时率、429/503 比例、连接失败比例。调度优先成功率,其次延迟,并设置最低门槛,低于门槛直接熔断。健康闭环越短,系统越稳。

3、易路代理在高并发采集里的更稳用法

如果你使用的是易路代理这类支持按用途建池与固定集合的代理能力,建议把“结构化”优先落地:采集任务绑定专用采集池,给每个出口设置并发上限与健康阈值;账号或敏感请求绑定低波动池;验收与测试另建独立池,避免互相污染。这样做的关键收益不是“IP更多”,而是故障可隔离、波动可控、调度可自愈,比随机轮换IP更不容易把问题放大成雪崩。

五、落地检查表,避免高并发下的典型事故

  • 连接池是否设置 maxTotal 与按代理维度的并发上限
  • connectTimeout、readTimeout、connectionRequestTimeout 是否齐全且合理
  • 是否有空闲连接回收与连接 TTL
  • 重试是否只对幂等请求生效,且有指数退避与抖动
  • 429/503 是否触发降速或熔断
  • 是否有每代理健康评分与熔断半开机制
  • 是否把采集池与账号池隔离,避免互相污染

把连接池做成可控资源,把重试做成有预算的恢复机制,再把代理池做成可自愈调度系统,高并发采集才会从“靠运气跑”变成“可长期跑”。