📝 主题:大水冲了龙王庙 —— 自家节点的“IP 拉黑”与限流危机
🚨 序章:速度的代价
搞定了第 7 天的数据一致性问题后,Scanner 终于学会了“核对账本”。但为了求稳,速度慢了不少。 我想着:“既然我已经把 AWS AMB 节点升到了 m5.large,带宽和 IOPS 都拉满了,那咱们就别客气了。”
我给 Alex 下令:“解除限速,火力全开!让 Scanner 用最快的速度去追主网高度!”
Alex 也不含糊,直接把 Scanner 的并发线程开到了最大。我满心期待地看着 Grafana 上的 TPS(每秒交易处理数)飙升,心想今天终于能早点下班了。
🎬 第一章:全线飘红
上午 10:30,TPS 刚冲到一个新高,监控大屏突然**“啪”**地一下,从绿色变成了刺眼的红色。
-
Scanner 日志:满屏的 HTTP 429 Too Many Requests 和 Connection Refused。
-
第一反应:AWS 挂了?AMB 宕机了?
-
排查:我冲进 AWS 控制台,发现 AMB 节点的 CPU 占用率只有 30%,内存也很健康。节点活着,但它拒绝和 Scanner 说话。
真相: 我在 CloudWatch 的网络监控里发现,Scanner 的出口 IP 流量被截断了。 结论:Scanner 因为请求太猛,被 AWS AMB 的防御机制当成了 DDoS 攻击者,直接把我们自己的 IP 给“拉黑”了(或者说是严重限流)。
🕵️♂️ 第二章:技术复盘 —— 为什么会被自己人打?
我拉着 Alex 进行了深度代码审查,发现了两个导致被封的“罪魁祸首”。
1. 短连接的轰炸 (No Keep-Alive)
Alex 的代码里,HTTP Client 配置非常简陋:
-
行为:每查一笔交易,就新建一个 TCP 连接,发请求,收数据,然后关闭连接。
-
HTTPS 的代价:AMB 使用 HTTPS Endpoint。这意味着每次请求都要进行:TCP 三次握手 + TLS 四次握手。
-
后果:Scanner 每秒钟试图建立 2000 次握手。这对服务器来说,简直就是 SYN Flood 攻击的特征!防火墙(AWS Shield)不拦你拦谁?
2. 死亡重试 (Death Spiral Retry)
代码里还有一个致命逻辑:
-
行为:如果请求返回错误(比如 429),Scanner 会立即重试,甚至并发重试。
-
后果:AMB 说“你慢点”,Scanner 说“我不!我就要快!”。
-
结局:越限流,重试越多;重试越多,限流越严。这是一个死循环。
🛠️ 第三章:Henry 的架构级自救
找到了病根,修复方案就清晰了。我们不需要改防火墙规则,我们需要**“学会礼貌”**。
1. 开启长连接 (HTTP Persistent Connection)
我要求 Alex 在 HTTP Client(比如 OkHttp 或 HttpClient)中强制开启 Keep-Alive。
-
原理:
-
不开:拨号 -> 说话 -> 挂断 -> 拨号 -> 说话 -> 挂断。
-
开启:拨号 -> 说话 -> 不挂断 -> 继续说话 -> 继续说话。
-
-
收益:
-
省去了 99% 的 TCP+TLS 握手消耗。
-
AMB 看到的不再是“每秒 2000 个新连接”,而是“几根稳定的长管道在传输数据”。WAF 立刻就不报警了。
-
2. 指数退避 (Exponential Backoff)
把“死缠烂打”的重试逻辑改掉。
-
新逻辑:
-
第一次失败:等 1 秒再试。
-
第二次失败:等 2 秒。
-
第三次失败:等 4 秒。
-
…
-
超过 5 次:报错人工介入。
-
-
效果:给服务器喘息的机会,也避免触发更高级别的封禁。
3. 主动限流 (Client-side Throttling)
我们不能指望服务器无限抗压。既然买了 m5.large,我就查了 AWS 文档,它的上限大概是 1500 RPS。
-
操作:我们在 Scanner 内部加了一个 RateLimiter,把发出的请求控制在 1200 RPS。
-
Henry 语录:“与其被别人被动限流,不如自己主动控制节奏。”
📚 第四章:运维深度问答 (Q&A)
Q1: 这个限流(429)的上限是 AMB 自己设置的吗?能改吗?
-
Henry: 是的,这是 AWS AMB 作为一个**托管服务(Managed Service)**的出厂设置。
-
它是写死在 AWS 基础设施里的(为了防止邻居受影响)。
-
怎么改? 你改不了参数。想提高上限?得加钱升级节点规格(比如升到 xlarge),或者开工单找 AWS 申请提升配额(很难)。
-
Q2: 为什么 HTTPS 必须要开 Keep-Alive?普通 HTTP 需要吗?
-
Henry:
-
HTTPS:必须开! 因为 TLS 握手涉及密钥交换和证书验证,非常消耗 CPU 和时间。不开的话,性能至少损失 40%。
-
HTTP:建议开。虽然没有 TLS 开销,但 TCP 三次握手也是成本。只要是高频请求,Keep-Alive 都是标配。
-
Q3: 拦截我的是我手动设置的安全组(SG)吗?
-
Henry: 不是。 SG 很笨,只看白名单。
-
拦截你的是 AWS Shield Standard(自动防 DDoS)或者 AMB 网关的 Throttling 策略。
-
这些是“隐形保镖”,默认开启且关不掉。你只能通过优化流量特征(比如用长连接)来避免激怒它们。
-




