知用网
霓虹主题四 · 更硬核的阅读氛围

网络连接超时自动重试:让程序更“抗造”

发布时间:2025-12-11 00:48:10 阅读:164 次

你有没有遇到过这种情况:写好的脚本跑着跑着,突然因为网络抖动断了连接,整个任务就卡死了?重新跑一遍费时费力,尤其是处理大批量数据或者调用外部 API 的时候,特别让人抓狂。

为什么需要自动重试

网络不是永远稳定的。服务器可能瞬时过载,DNS 解析可能延迟,Wi-Fi 信号可能波动。这些都可能导致一次请求超时。但大多数情况下,几秒后再试一次,事情就过去了。与其手动重启程序,不如让代码自己“再努努力”。

简单的重试逻辑长什么样

以 Python 为例,最基础的重试可以用一个 while 循环加 try-except 实现:

import requests
import time

max_retries = 3
retry_count = 0

while retry_count < max_retries:
    try:
        response = requests.get('https://api.example.com/data', timeout=5)
        print(response.json())
        break  # 成功就跳出循环
    except requests.exceptions.Timeout:
        retry_count += 1
        print(f'请求超时,第 {retry_count} 次重试...')
        time.sleep(2)  # 等两秒再试
    except requests.exceptions.RequestException as e:
        print(f'请求出错:{e}')
        break

别傻等,指数退避更聪明

如果每次失败都隔 2 秒重试,前几次可能还好,但如果连续失败,说明问题没那么快恢复。这时候可以采用“指数退避”策略:第一次等 1 秒,第二次等 2 秒,第三次等 4 秒……避免在短时间内疯狂请求给服务器添堵。

稍微改一下上面的逻辑:

import time
import random

def make_request_with_backoff():
    max_retries = 5
    for i in range(max_retries):
        try:
            return requests.get('https://api.example.com/data', timeout=5)
        except requests.exceptions.Timeout:
            if i == max_retries - 1:
                raise  # 最后一次也失败,抛出异常
            wait_time = (2 ** i) + random.uniform(0, 1)  # 加点随机性
            time.sleep(wait_time)

用现成轮子更省心

自己写重试逻辑容易漏掉边界情况。Python 里有个很实用的库叫 tenacity,专门干这个事。

先安装:

pip install tenacity

然后这样用:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, max=10))
def fetch_data():
    response = requests.get('https://api.example.com/data', timeout=5)
    return response.json()

# 调用它,失败会自动重试
print(fetch_data())

上面这段代码的意思是:最多尝试 5 次,等待时间按指数增长(1s, 2s, 4s...),最长不超过 10 秒。简洁又可靠。

重试不是万能的

有些错误重试也没用,比如认证失败、接口不存在。盲目重试反而浪费资源。建议只对网络超时、连接中断这类临时性错误(transient errors)启用重试。

还可以结合日志记录,每次重试都留下痕迹,方便排查问题。线上服务中,搭配监控和告警,能让系统更健壮。

说到底,网络连接超时自动重试不是炫技,而是让程序更有容错能力。就像坐地铁,偶尔错过一站没关系,下一站还能赶上——代码也该有这样的弹性。