java中用try-catch实现健壮爬虫重试逻辑,核心是分类异常(仅重试sockettimeoutexception等可恢复异常)、设最大重试次数(3–5次)、加指数退避与随机抖动、记录日志,并下沉至http客户端统一配置超时与重试。

Java中用try-catch实现网络爬虫的健壮重试逻辑,核心不是简单套一层catch,而是结合异常分类、指数退避、最大重试次数和连接/读取超时控制,让失败请求有机会恢复,又不无限阻塞或压垮目标站点。
区分可重试与不可重试异常
不是所有异常都该重试。比如404(Not Found)或403(Forbidden)是服务端明确拒绝,重试无意义;而SocketTimeoutException、ConnectException、UnknownHostException通常因网络抖动或服务瞬时不可用,适合重试。
- 建议重试的异常:SocketTimeoutException、ConnectException、UnknownHostException、SSLHandshakeException(部分场景)、IOException(需结合上下文判断)
- 不建议重试的异常:HttpResponseException(如4xx/5xx中明确不可恢复的状态码)、ParseException、NullPointerException(说明代码逻辑有缺陷)
- 可用Apache HttpClient的
DefaultConnectionKeepAliveStrategy配合RetryStrategy,或手动在catch中判断异常类型再决定是否重试
实现带退避策略的循环重试
连续立即重试可能加重服务压力,也容易被限流。应采用指数退避(Exponential Backoff):第1次失败后等1秒,第2次等2秒,第3次等4秒……并加入随机扰动避免“重试风暴”。
- 用
Thread.sleep((long) (baseDelayMs * Math.pow(2, retryCount) * (0.8 + 0.4 * Math.random())))计算等待时间 - 设置最大重试次数(如3~5次),超过则抛出原始异常或封装为自定义业务异常
- 每次重试前记录日志,包含URL、当前重试次数、异常类型,便于问题定位
在HTTP客户端层面统一配置超时与重试
把重试逻辑下沉到HTTP客户端(如HttpClient或OkHttp),比在每个请求方法里写重复的try-catch更干净、可靠。
- HttpClient示例:用
HttpRequestRetryHandler自定义重试判定,配合RequestConfig设置connectTimeout、socketTimeout - OkHttp示例:通过
Interceptor拦截失败响应,对特定异常或5xx状态码触发重试,并控制重试间隔 - 避免在重试时重复提交表单或POST请求(防止重复下单等副作用),GET请求才默认允许重试
结合断路器防止雪崩式失败
当某个域名或接口持续失败(如连续5次超时),可临时熔断,跳过该目标一段时间(如1分钟),避免线程长时间阻塞或无效重试。
- 可用轻量级库如resilience4j的
CircuitBreaker,或自己用ConcurrentHashMap+AtomicLong维护失败计数和时间戳 - 熔断期间返回缓存结果、默认值或快速失败异常,不发起真实网络请求
- 熔断期过后自动半开(half-open),放行1个请求试探,成功则关闭断路器,失败则重置计时
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











