告警场景担心两件事:一是接口调用超时程序卡住,二是临时网络抖动导致告警发不出去却无人察觉。预警通知接口本身很稳定,但客户端如果不设超时、不做重试,一次网络波动就可能让一条 P0 告警石沉大海。本文介绍如何为互亿无线预警通知接口配置合理的超时…
告警场景担心两件事:一是接口调用超时程序卡住,二是临时网络抖动导致告警发不出去却无人察觉。预警通知接口本身很稳定,但客户端如果不设超时、不做重试,一次网络波动就可能让一条 P0 告警石沉大海。本文介绍如何为互亿无线预警通知接口配置合理的超时与重试策略。
为什么必须设置接口超时
HTTP 请求如果不显式设置超时,底层可能无限期等待,导致告警发送线程被挂住,后续告警排队积压。建议连接超时设为 5 秒、读取超时设为 10 秒,既能容忍正常网络波动,又能在故障时快速失败。一个常被忽略的点是:超时要分两层设置,连接超时负责"连不上时快速放弃",读取超时负责"连上了但响应慢时兜底",两者不能只设一个值。
超时与重试的代码示例
下面用 Python 实现带指数退避的重试逻辑,并区分网络异常与业务错误:
import requests, time
def send_with_retry(payload, retries=3):
url = "https://api.ihuyi.com/sms/Submit.json"
for i in range(retries):
try:
r = requests.post(url, data=payload, timeout=(5, 10))
res = r.json()
if res.get("code") == 2:
return res
# 业务错误(余额不足/号码错误)不重试
print("业务错误,不重试:", res)
return res
except requests.RequestException as e:
print("网络异常,第%d次:%s" % (i + 1, e))
time.sleep(2 ** i) # 退避 1s、2s、4s
return None
重试策略的关键要点
- 只对网络异常和 5xx 重试,业务返回码(如余额不足、号码格式错误)不要重试,重试也不会成功。
- 采用指数退避,间隔 1s、2s、4s,避免在服务端故障时形成二次冲击。
- 重试仍失败时,必须把失败记录落到本地日志或告警平台,人工介入。
- 接口返回 code=2 才算提交成功,拿到 smsid 后还要靠回调确认实际送达。
- 给重试加一个总时长上限,例如 8 秒内必须出结果,不能让告警发送本身阻塞监控流程。
超时重试与去重的配合
重试主要的副作用是重复发送。由于接口是按成功计费,重试成功后不应再重发同一条。建议在业务侧用告警指纹(主机名+指标+时间窗)做幂等控制,30 秒内同指纹只发一次。这样既有助于告警不丢失,又避免值班人被重复电话轰炸。可参考的伪代码:
def send_alert_idempotent(fingerprint, payload):
if cache_exists(fingerprint, ttl=30):
return "duplicate"
res = send_with_retry(payload)
if res and res.get("code") == 2:
cache_set(fingerprint, res["smsid"], ttl=30)
return res
超时与重试参数怎么取值
参数不是拍脑袋定的,建议按通道特点区分:短信接口网络往返通常在一秒内,连接超时 5 秒、读取超时 10 秒已经很宽裕;语音合成稍微慢一点,读取超时可以放到 15 秒。重试次数统一设 3 次即可,再多只会放大故障时的冲击。
| 参数 | 建议值 | 说明 |
|---|---|---|
| 连接超时 | 5 秒 | 连不上时快速放弃 |
| 读取超时 | 10-15 秒 | 语音可放宽到 15 秒 |
| 重试次数 | 3 次 | 指数退避 1/2/4 秒 |
| 总预算 | 8-20 秒 | 不能阻塞监控主流程 |
失败的请求一定要落日志,记录时间、手机号、返回码,这样出问题时能还原现场。互亿无线按成功计费,重试成功那一次才计费,多次失败不会产生费用。
互亿无线按成功计费、失败不计费,重试不会产生多余费用,配合合理的超时与退避策略,告警链路更稳。想动手验证可以注册免费试用。