资讯动态

DDoS防御别只加带宽:流量型、连接型与应用层攻击拆解

发布时间:2026/10/28 2:44:44 来源:尧图企业网站定制
DDoS 这个词在运维和安全圈里被说得太笼统了笼统到很多人一听告警就条件反射地去加带宽、换高防结果该稳的还是不稳。我印象很深的一次值班凌晨一点半业务侧报页面加载不出来我第一反应是入口流量被打满了登录监控一看出口带宽才用了不到三成但服务器的连接数曲线已经顶到天花板应用进程的 CPU 反而是空闲的。那次之后我才真正把流量型、连接型、应用层这三类消耗拆开来看——它们表面上都表现为服务不可用实际上是三场完全不同性质的资源争夺战抢的东西分别是网络管道、内核的会话状态表、以及应用进程的处理时间。你只有判断出对手在抢哪一样处置动作才有意义。这篇内容我按自己的理解顺序梳理一遍三类攻击各自消耗什么、从哪些指标能看出来、防御端有哪些真能落地的手段以及我踩过的几个典型误判。适合已经上手在管服务、被这类问题折磨过的同行看也适合刚接触这块、还在背概念的朋友对照着建立整体框架。1. 三种消耗其实在抢三种不同的资源1.1 带宽、连接表、CPU时间——三条互不相干的瓶颈先把这三件事在脑子里摆正位置。网络数据进入你的服务器要经过几道关口链路上的物理带宽、网卡与内核协议栈的包处理能力、内核为每个连接维护的状态记录、最后才是应用进程读走数据并执行业务逻辑。这三类打法分别卡在不同的关口上所以表现出来的症状完全不一样。流量型消耗的目标是最靠外的一层把链路带宽灌满或者把网络设备的包处理能力打满。这时候服务器本身可能一点事没有CPU 空着内存空着但数据包在路上就进不来了外部请求超时健康检查失败。它比拼的是谁的带宽和清洗能力更厚跟你的代码质量、数据库优化毫无关系。连接型消耗往内走了一层目标是内核的连接表和端口资源。它不追求把管道灌满而是用极其廉价的方式让你维持海量的半成品连接把内核的会话记录槽位耗光。槽位满了之后正常用户的三次握手都排不进来表现为连接超时或者握手失败但带宽曲线可能只涨了一点点CPU 也很淡定。应用层消耗最靠内目标是应用进程和工作线程。请求完全合规三次握手正常完成HTTP 报文格式挑不出毛病但它专挑那些每处理一次都很贵的接口反复打——耗 CPU 的计算、耗数据库的复杂查询、耗第三方调用的慢接口。带宽没满、连接数不高、内核一切正常就是业务的响应时间一路飙线程池被占死。我在实际排查里最常用的一个判断动作就是同时看三条曲线入口带宽利用率、并发连接数尤其是处于非 ESTABLISHED 状态的数量、应用的平均响应时间与线程池排队数。哪条先异常、哪条最先顶到上限基本就锁定了攻击类型。这个动作花不了三十秒但能省掉后面半小时的瞎折腾。1.2 为什么同样打不开处置动作却完全相反这一小节是我最想强调的因为我见过太多因为搞错类型而越救越死的案例。如果你把应用层攻击误判成流量型最可能做的动作是加大带宽、上高防清洗。结果是流量确实被放行了因为人家流量本来就不大请求长驱直入打到应用层你那点线程池照样被占满钱花了问题没解决。更糟的是部分清洗设备会做会话保持和延迟放行反而让本就宝贵的线程挂得更久。反过来把流量型误判成应用层去调线程池大小、加机器也是白费。包在链路上就被丢了你后端加十台机器也收不到请求扩容的钱等于打水漂。还有一种更隐蔽的误判把连接型攻击当成流量型。有些人看到告警第一反应是洪水来了其实对方发的是大量小包带宽占用并不高但每秒包数pps极高。很多设备标称的带宽单位是 bit/s标称能力很漂亮实际包处理能力pps才是短板。小包打过来带宽看着还有余量设备先被打挂了。我总结下来一句话流量型靠管道和清洗连接型靠内核和限速应用层靠识别和限频。三条路的技术栈几乎没有重叠方向错了就是在错误的战场上堆积资源。所以下面三章我按原理—指标—手段这个顺序分别拆开讲中间穿插一些我实际踩过的具体细节。2. 流量型消耗把出口管道灌满的最粗暴打法2.1 反射放大借别人的服务器当放大器流量型里最经典也最难缠的一类是反射放大。它的思路非常省力攻击方并不需要自己有巨大的带宽只需要伪造源地址把请求发给互联网上那些有问必答的服务让这些服务把体积大得多的应答全部回给被攻击的目标。这就好比有人用你的名字在网上订了一万份外卖全部送到别人家门口送餐员的数量和你的下单量完全不成比例。它成立需要三个条件同时具备理解这三条比记住任何工具都有用协议不需要先建立会话。基于 UDP 的查询类服务天然满足因为没有握手服务端收到包就直接回无法验证源地址真实性。应答体积显著大于请求体积。这个比值就是放大倍数公开的分析报告里一些查询类协议在特定应答下能到几十倍甚至数百倍量级这也是为什么这类打法在历史上造成过单次数百 Gbps 的流量事件。互联网上存在大量配置不当、对任意来源都提供应答的服务实例。这一条是根本原因也是防御侧真正能改善的地方。防御上作为普通服务方你其实做不了太多因为流量不是从你的网络产生的。你能做的三件事一是接入上游清洗把流量在骨干侧牵引掉二是用 Anycast 一类的地址分散方案把同一地址的服务点铺到多个位置让流量被就近吸收三是对被攻击的域名做灰度降级先把非核心业务的解析摘掉保核心。这里有个我踩过的坑很多人只做第一步以为买了清洗就万事大吉实际上清洗服务往往有回源带宽的限额一旦攻击流量超过限额回源链路直接被压死业务照样断。所以签这类服务时一定要盯清楚回源带宽和清洗阈值这两个数字而不是只看标称的防护峰值。至于根治属于整个生态层面的问题网络侧对源地址做严格校验、查询类服务默认不对外网开放递归这两件事做了放大的土壤就没了。作为使用方我建议至少把自己名下的这类对外服务全部自查一遍关闭不必要的外部查询能力——这既是保护别人也是防止自家的服务器被当成帮凶。2.2 从三个指标里认出小包洪水还是大包洪峰流量型攻击的识别比想象中简单关键看你有没有埋对指标。我一般看这三个指标含义异常时说明什么入口 bps比特/秒链路带宽占用冲高到接近链路容量典型的大包洪峰或正常大流量入口 pps包/秒设备包处理压力冲高但 bps 不高典型的小包洪水平均包长bps ÷ pps ÷ 8单包平均字节数突然掉到几十字节说明对方在用极小的包拼 pps平均包长这个指标特别管用但很多监控面板默认不给需要自己算或者让采集侧加上。我遇到过一种情况带宽监控显示只涨了 15%看着风平浪静结果防火墙先扛不住了因为对方是拿几十字节的小包刷 pps设备的会话建立速率被瞬间打爆。如果当时我先看了 pps 和平均包长就不会浪费二十分钟去查后端。还有一个细节协议分布。流量型攻击在协议分布上通常极度偏斜某一类协议突然占到 90% 以上是很强的信号。正常业务的流量分布一般是相对平滑的HTTP、HTTPS、DNS、NTP 各有各的比例。看到某一类异常膨胀基本就能确定对方的打法也就能针对性地在边界设备上做过滤。不过过滤规则要慎重我曾经过于激进地整段封禁某类协议结果把自己内部的时间同步和解析都影响了属于典型的误伤后来改成只丢弃来自外网、目的为内部该服务端口、且源地址不在白名单这种更精细的规则才稳妥。2.3 源站硬扛这件事越早放弃越好有种想法我听过很多次我们机房带宽很大硬扛一下问题不大。 这个思路在一种场景下勉强成立攻击量远低于你的链路容量且你边缘设备的 pps 能力足够。但现实是这个前提几乎不成立因为攻击方调整成本极低而你的链路容量是固定的。更重要的是即使你真的扛住了被占满的链路会连带影响同机房的其他业务你的上行设备会持续高负载故障风险成倍上升。真正的解法是把流量在够靠前的位置就处理掉源站始终只承接已经过筛的干净流量。这也是为什么我一直建议把源站的地址做得尽量隐蔽不做直接的公网解析、回源走专线或固定通道、对外只暴露中间层地址。源站地址一旦泄露前面做的所有清洗工作都可能被绕过。3. 连接型消耗不打满带宽专打状态表3.1 半开连接是怎么把队列占住的要讲清楚这类攻击得先回顾一下三次握手。客户端发 SYN服务端回 SYN-ACK 并把这条连接放进半开队列等待最终确认收到 ACK 后连接从半开队列移到已完成队列等待应用进程调用 accept 取走。这里有个天然的脆弱点半开队列的长度是有上限的内核不会无限接客。经典的 SYN 洪水就是狂发伪造源地址的 SYN 包服务端老老实实为每一个都分配一个半开槽位并回 SYN-ACK但那个伪造的地址根本不会回 ACK。槽位被占满、超时后才释放而新的 SYN 进来没地方放正常的用户握手就失败了。整个过程攻击方几乎不消耗什么资源防守方却被拖进了状态维护的泥潭。内核早就给了对策也就是SYN Cookie不再为半开连接预分配状态而是把连接信息编码进 SYN-ACK 的序列号里等对方回 ACK 时再还原校验。开启之后半开队列被撑爆的风险大幅下降。在 Linux 上是这个开关# 1 启用2 仅在队列满时启用0 关闭 sysctl -w net.ipv4.tcp_syncookies1我个人的建议是设成 1 而不是 2。设 2 看起来更聪明只在压力大时才启用但代价是流量陡增的瞬间你可能正在切换而那个瞬间恰恰是最危险的。常开的问题是会丢失一部分 TCP 选项信息比如窗口缩放对长肥管道高延迟大带宽的吞吐有一定影响但对绝大多数面向公网的业务这点影响远小于被打穿的风险。与它配套的还有两个参数net.ipv4.tcp_max_syn_backlog管半开队列net.core.somaxconn和 listen 时传的 backlog 共同决定已完成队列。这里有个非常常见的坑——很多框架的 listen backlog 默认值偏小你内核参数调得再大应用只申请了很小的 backlog队列照样早早溢出。我在一次压测里就遇到过这个内核看着挺宽裕实际吞吐上不去最后发现是应用侧配置没改。3.2 端口、会话记录、文件句柄的连锁枯竭连接型攻击的第二层杀伤在于它会顺着资源链条往下传染。几个常见的连锁反应端口耗尽。如果你的服务作为客户端去连后端比如反向代理连上游每条连接会占用一个本地临时端口端口范围是有限的默认大约两三万个。连接不释放端口就被占住新的上游连接建立不了前端表现就是 502 或超时。这种故障特别迷惑人因为前端看着完全正常问题全在后端无法建连。会话跟踪表打满。如果边界上开了连接跟踪每条流都会占一个条目。条目满了之后内核会直接丢弃新流日志里会看到大量 table full, dropping packet。这个报错很有辨识度看到它基本可以确定是连接数层面的问题。文件句柄耗尽。每条连接在进程里对应一个文件描述符进程的 fd 上限ulimit -n打满后日志里会刷 Too many open files甚至导致配置文件都读不进来故障表现离原始原因非常远。我把这几条整理成一张对照表排查时按顺序看观察点命令或指标打满后的典型现象会话跟踪条目cat /proc/sys/net/netfilter/nf_conntrack_count对比nf_conntrack_max内核日志刷 table full新连接直接被丢本地临时端口ss -s看 TIME-WAIT 与已用端口连上游失败报无法分配地址进程文件句柄ls /proc/pid/fd | wc -l对比ulimit -n日志刷 Too many open files半开与完成队列ss -lnt看 Send-Q / Recv-Q队列溢出计数上涨握手失败率升高提示连接数告警一定要区分状态。ESTABLISHED 多和 SYN-RECV 多是两个完全不同的问题前者可能是业务增长或者慢请求堆积后者才更像攻击。只看总数不看状态分布是我早期最常犯的错误。3.3 真正值得动的几个内核参数以及它们的取舍参数调优这块有很多流传甚广但需要谨慎对待的说法。我按自己的实践经验说几个真正有用的以及为什么。net.ipv4.tcp_syncookies1前面讲过常开。net.ipv4.tcp_max_syn_backlog适当调大比如 8192 到 16384 区间具体看并发量级不是越大越好——它只是缓冲配合 Cookie 之后意义有限调太大只是浪费一点内存。net.core.somaxconn调到 4096 或更高同时务必去改应用侧的 listen backlog两头对齐才有意义。关于 TIME-WAIT我一直反对盲目开tcp_tw_recycle新内核已经移除tcp_tw_reuse在客户端场景可以开服务端要谨慎因为它会让一些依赖时间戳的安全校验变松。TIME-WAIT 本身是保护机制不是敌人靠缩短tcp_fin_timeout硬压时间在真正的连接攻击面前杯水车薪。net.ipv4.tcp_abort_on_overflow这个参数要特别小心。设成 1 时完成队列溢出会直接回 RST好处是客户端快速失败坏处是在瞬时突发下会误杀正常用户。我一般保持默认 0宁可让客户端重试也不要主动 RST。还有一个被低估的手段是限速比如按源地址限制新建连接速率。这在连接型攻击下非常有效因为对方的连接几乎全部来自有限的源地址池或者可识别的异常地址分布。配合边界设备做每秒新建连接数CPS的限制比在内核里死磕参数要直接得多。4. 应用层消耗请求看起来很合法但每一条都很贵4.1 先算清楚一次请求在后端到底花了多少资源应用层攻击最阴的地方在于它不发畸形包握手正常、报文格式规范、字段齐全边界设备看不出任何异常。它的逻辑是找到你最贵的那个接口然后反复调用。所以防御的第一步不是买设备而是先摸清自己的接口成本分布。举个具体的例子。一个登录接口如果密码哈希用的是成本参数较高的算法单次校验可能要占用几十毫秒的 CPU 时间。这几十毫秒在正常流量下完全无感但换算一下单核一秒理论上最多处理二三十次一台四核机器大概也就百次出头。也就是说每秒一百多个并发请求就能把这台机器的 CPU 吃干净而这个 QPS 对一个有正常缓存配置的网站来说根本不算什么流量带宽、连接数全都在合理范围内。这就是所谓的低成本攻击、高成本防守。再比如搜索接口。如果查询条件没走索引或者带了模糊匹配单次查询可能扫几百万行耗时数百毫秒还会把数据库的连接池占满。攻击方只需要构造那些最不走索引的参数组合几百个并发就能把整个库拖垮。所以我一直坚持一个做法给核心接口做单位成本画像。方法很朴素在压测环境里对每个接口做单并发基准测试记录单次请求的 CPU 时间、数据库耗时、下游调用次数然后算出一个单次成本。有了这张表你就知道哪些接口是便宜的大路货哪些是贵重的稀缺资源。贵重接口必须单独隔离——独立的线程池、独立的限流阈值、独立的降级开关。这一条如果早做能挡掉一大半应用层攻击造成的伤害。4.2 慢速请求与长连接把线程挂住而不是打满应用层消耗还有一类手法它不追求单位时间内的请求数量而是追求单条请求占用资源的时间。逻辑很简单如果你的工作线程是一请求一线程模型那么把一个请求拖到 30 秒才结束这一个线程就白白被占 30 秒。几百条这样的请求线程池就空了而这段时间内它只发了几百个请求每秒个位数任何基于 QPS 的限流阈值都不会触发。具体怎么拖用极慢的速度发请求头、发请求体或者发一个声明了很大长度但就是不传完的报文。服务端为了等这个报文会保持连接并占用工作线程。这类打法的特点是并发连接数不高、QPS 极低、CPU 极低、但活跃线程数和平均响应时间飙升。对策的核心是超时和隔离而不是加大线程池给请求头和请求体的读取设置明确的、较短的时间上限不要让默认配置替你决定。限制单个连接同时能处理的请求数启用请求排队上限超过就快速失败。尽量使用异步非阻塞模型或者在阻塞模型前端加一层事件驱动的接入层把等待慢客户端的成本从工作线程身上剥离。对超长的请求体做硬性大小限制超过直接拒绝不要先收完再判断。我在这块吃过的教训是超时时间不能只设一层。曾经有个服务网关设了 60 秒超时应用设了 30 秒但连接本身的读取超时没设结果慢速请求在连接层可以无限期挂着前两层超时根本没机会触发。后来统一梳理了一遍从最外层到最内层按递减顺序设置连接读超时 10 秒、应用处理超时 20 秒、网关总超时 30 秒任何一层先到就断开问题才算彻底解决。还有一类和业务强相关的消耗依赖放大。一个页面请求如果串行调用五个下游服务每个下游平均 100 毫秒这个请求就占 500 毫秒。攻击方只要盯着这个页面打就能用极低的 QPS 把你的线程和下游连接池同时占满并且压力会沿着调用链传导到那些本来毫无防备的内部服务。我见过的内部服务被拖垮的案例绝大多数都是这么来的——外网入口只被打了几百个请求。4.3 从耗时分布和日志里把贵请求揪出来应用层攻击的排查靠的是分布而不是均值。均值会被正常的慢请求稀释也可能被攻击请求拉高但看不出结构。我一般看三个东西第一是响应时间的分位数。p50、p95、p99 一起看。如果 p50 基本没变p99 涨到离谱说明大部分请求是好的少数请求极慢——这要么是慢请求堆积要么是资源竞争。如果 p50 也在涨说明整体都在变慢可能是 CPU 或数据库层面的整体压力。第二是接口维度的请求量分布。正常情况下流量在各接口上应该大致符合业务逻辑形成相对稳定的比例。攻击时这个比例会突然失衡某个原本占比 2% 的接口忽然占到 40%。这个信号极其明显几乎可以直接定位。所以我一直建议在网关或应用层做按路径的请求量统计粒度到具体的接口甚至具体的参数组合。第三是按源地址、来源特征的聚类。应用层攻击往往来自相对集中的地址池或者有明显的特征共性比如 UA 完全一致、请求头缺失、参数构造规律、访问顺序固定。把这些维度做上采样能比较快地圈出攻击流量。定位之后的手段按代价从低到高排列缓存把贵接口的结果缓存住让成本从每次算变成算一次、限频按地址、按会话、按接口多维度限、排队与降级贵接口独立小线程池满了就返回稍后重试、人机校验对可疑会话加验证代价是体验、流量清洗把已知特征在边界丢弃。顺序不要搞反缓存和限频的性价比永远最高清洗应该是最后手段。提示限频的阈值不要凭感觉定。我建议的做法是统计线上真实用户请求量的 p99.9把阈值设在它的两到三倍。低于这个值会误伤正常用户高于这个值则起不到保护作用。这个数字必须靠数据得出我见过太多凭直觉拍脑袋设阈值结果要么形同虚设、要么把正常用户挡在门外的案例。5. 三类攻击的识别对照与处置优先级5.1 一张能贴在工位上的对照表排查的时候最怕的就是慌乱中忘了看哪个指标。我把三类攻击最容易区分的特征整理成下表实际值班时基本能在一两分钟内完成初判观察维度流量型消耗连接型消耗应用层消耗入口带宽明显冲高接近或顶到上限涨幅有限通常不显眼几乎正常每秒包数 pps可能极高小包洪水时偏高但不极端正常平均包长可能骤降到几十字节正常偏小正常并发连接数不明显急剧上升尤其是 SYN-RECV 等中间态上升但以 ESTABLISHED 和排队为主CPU 使用率网络软中断高应用本身不高内核态偏高应用不高应用进程用户态高数据库与下游无异常通常无异常连接池占满、慢查询暴涨故障表现请求超时、健康检查失败握手失败、连不上、上游连不通响应极慢、线程池排满、部分接口 5xx第一处置动作上游牵引清洗、就近吸收开启 Cookie、限制新建速率、检查队列缓存、限频、接口隔离降级这张表里我最看重的是CPU 使用率的类型和数据库与下游这两行。因为带宽和连接数有时候会因为监控采集间隔而看不准但 CPU 用户态和内核态的分离加上下游是否被拖累能非常干净地区分内核在忙和应用在忙。5.2 处置顺序的经验先保命再定位最后才追源很多人在攻击发生时第一反应是我要找出是谁打的。这个顺序在实战里是错的。正确的优先级是先让业务活下来再收集证据最后才是追溯。因为攻击持续期间你丢失的每一分钟都是真实损失而追溯的收益远没有那么即时。具体我一般这么做第一步做容量腾挪把非核心功能摘掉、把静态资源切到独立的缓存层、把贵接口的入口关掉或者加验证用最快的速度把核心链路腾出来。这一步不看原因只看效果。第二步做限流兜底在入口按地址和接口做粗粒度限流宁可误伤一点也要止住血。第三步才开始分层定位用前面那张对照表判断类型然后做针对性处置。第四步是留证据把攻击期间的抓包、日志、地址分布、请求特征保存下来这部分对后续优化规则非常关键。有个细节值得说抓包一定要提前做不要等打起来才抓。攻击期间在高负载机器上抓包本身就会加剧问题而且很容易漏掉关键时段。我的做法是在边界设备上常开抽样留存只保留报文头部和少量载荷占用很小出事时直接回捞比临时上阵靠谱得多。5.3 把自己的容量基线量出来别等被打时才知道上限这条是我最想强调的一条经验所有防御动作的前提是你知道自己能扛多少。没有基线限流阈值定不了、扩容决策做不了、清洗服务的规格也选不准。基线的测量方法不复杂但需要认真做在和生产环境尽量一致的配置下对核心链路做阶梯加压找到三个拐点——响应时间开始明显上升的点、错误率开始上升的点、系统彻底失去响应的点。第一个点就是你的安全工作区间上限日常告警应该设在它的 70% 到 80%。测的时候有几个容易忽略的点。一是要测混合场景单一接口压测的结论往往过于乐观真实流量是混合的资源争抢更严重。二是要测依赖降级场景把缓存关掉、把某个下游模拟成慢响应看看系统还能撑多久——应用层攻击恰恰就是制造这种场景。三是要测连接层面的上限包括新建连接速率和并发连接数这两项和 QPS 是独立的很多系统 QPS 能扛很高但并发连接数一上来就不行了。我们之前做过一次完整的基线测量结论挺反直觉系统能扛住的 QPS 比预估低很多但能扛住的并发连接数比预估高很多。也就是说如果对方用慢速请求的方式打我们能撑比预期更久但如果对方用高并发的快速请求打我们的崩溃点会来得更早。有了这个结论之后限流策略就明确了——重点限制新建连接速率和每秒请求数而不是限制并发连接总数。6. 一次混合型攻击的完整排查链路复盘6.1 现象服务没挂但成功率掉到六成真实世界里的攻击很少是纯粹的一种混合打法才是常态这也是为什么前面要分类讲清楚——分类不是目的是为了在混合场景下能拆开看。我复盘一次印象比较深的经历。那次的现象很怪服务始终没有完全挂掉一直有响应但请求成功率从 99.9% 掉到了 60% 左右持续了将近四十分钟。没有明显的错误峰值没有进程崩溃没有重启监控大盘看上去哪儿都不太对但哪儿都没红。值班同事第一反应是数据库抖动查了一轮没发现异常。第二反应是某个下游不稳定逐个排查也正常。这就属于最难搞的类型——症状模糊但影响巨大。我现在回看当时最大的问题是排查顺序没有章法东看一块西看一块浪费了二十多分钟。后来我固化成了一套固定顺序从外到内一层层剥效率高得多。6.2 逐层剥离从入口流量到应用耗时的固定顺序那次最后定型的顺序是这样我建议你直接拿去用第一层看入口流量和包特征。带宽涨幅不到 20%pps 涨了将近三倍平均包长从正常的几百字节掉到了八十字节左右。这就已经有信号了pps 涨得远超带宽说明对方在用大量小包。但仅仅这一层还不足以解释 40% 的失败率因为带宽还有很大余量。第二层看连接状态分布。并发连接总数涨了两倍多其中 ESTABLISHED 占大头SYN-RECV 只是小幅上升。这一条很关键——它排除了纯 SYN 洪水的可能。SYN-RECV 占比不高说明对方不是靠伪造握手来打而是真的把连接建起来了。第三层看应用层的接口分布。这一步直接定位了问题。按路径统计的请求量里一个原本只占 1.5% 的导出类接口占比突然升到了 45%。这个接口会做复杂的数据聚合单次耗时在秒级而且会占用数据库的长连接。攻击方用大量真实建立的连接反复调这个接口同时每个连接还保持着不怎么发数据的状态。第四层看线程池和下游。应用线程池排队数持续增长数据库连接池占用率达到 100%慢查询日志里全是那个导出接口相关的语句。到这儿整条链路就闭合了。所以这是一次典型的混合打法用大量小包和高频连接维持压力、消耗网络层的处理能力同时用真实连接精准打击最贵的接口把应用层的线程和数据库连接吃干净。单看任何一层都不足以致命三层叠加起来就造成了 40% 的失败率。这也解释了为什么当时单看某个监控都觉得还好——每一层的压力都只有中等但合起来就是致命的。处置动作也很明确先把那个导出接口整体下线换成异步任务提交的方式然后对新建连接速率做限制最后在入口把 pps 层面的异常特征做过滤。三项做完成功率在几分钟内回到 99% 以上。6.3 复盘当时缺的那几个监控项事后复盘我列了几条当时确实没有、后来补上的东西价值比任何设备采购都高第一个是按接口维度的请求占比监控和异常告警。这个能力做起来极其便宜就是在网关层按路径做计数统计设一个占比偏离基线超过阈值的告警。按当时的情况这个告警能在两分钟内把问题指出来而不是花二十分钟逐个排查下游。第二个是平均包长的实时曲线。这个指标不常被默认采集但对判断流量型和小包混合型攻击极有价值而且计算成本几乎为零。第三个是线程池排队数与下游连接池占用率的联合告警。单独看线程池可能只是有点忙单独看连接池也可能只是有点紧但两者同时向上几乎必然是有贵接口被打或者有慢依赖。第四个是单接口成本画像表也就是前面提到的那个每次调用花多少资源的表。有了它在告警发生时你能立刻知道这个接口被打意味着什么量级的压力判断速度完全不一样。当时我们完全靠现场估算慢了很多。最后分享一个我自己养成的习惯每次处理完这类问题我都会在事后写一段如果重来一次前三分钟我会做什么的复盘记录。写了七八次之后我发现前三分钟的动作基本固定下来了——看三条曲线、看连接状态分布、看接口占比、然后按类型套处置模板。这些写下来的东西比任何手册都管用因为它们是从真实的错误里长出来的而不是从文档里抄来的。另外还有一个容易被忽略的点三类攻击的防御能力建设本质上是在做成本对比。对方用越便宜的手段你就越需要一个同样便宜的防线。带宽很贵连接状态也很贵但缓存、限频、超时这些手段几乎是免费的。我现在的思路很明确——先把所有免费或便宜的防线做扎实让对方的攻击成本被迫抬高再去考虑那些昂贵的清洗和扩容手段。这个顺序反了就会变成一直在花钱补窟窿。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑