带宽跑满只是表象,业务卡顿的真正瓶颈往往在连接并发、应用处理速度或后端服务上,盲目加大带宽只会增加成本,不会让页面变快。
你盯着监控面板,入口带宽曲线已经平得和直线一样,用户却还在群里喊“网页打开转圈”,这时候的第一反应是“升级带宽”,但冷静下来想想:带宽是服务器和外界之间的管道,管道再粗,如果源头的水厂不给力,出水口依然细得像滴眼药水,带宽跑满和业务卡顿,更像是同一次事故的两个症状,而不是简单的因果关系,要解决“服务器带宽跑满但网站还是卡”的问题,得先把真正的瓶颈挖出来。
服务器带宽跑满但网站还是卡?先理清这几点
先做一次简单的思维切换:带宽是传输通道,应用是处理引擎,通道再宽,引擎处理不过来,请求依然要排队等待响应,如果瓶颈在应用层,带宽跑满只是一个连带结果,比如一个请求需要查数据库,数据库慢,连接就一直挂着,每一条挂着的连接都占着带宽和内存,当连接数达到上限,新的请求进不来,业务就卡死了。
出现“带宽跑满但业务很卡怎么办”的疑问时,你需要分清三种情况:
- 带宽持续跑满,同时CPU和内存使用率都很低,这说明数据只是“过路”,没有消耗计算资源,很可能在传输大量静态文件或被人恶意刷流量。
- 带宽跑满,CPU也居高不下,这可能是应用逻辑过于复杂、循环计算太多,或者数据库查询慢导致进程堆积。
- 带宽并没有真正跑满,只是监控显示接近峰值,业务却已经卡住,这大概率是连接数耗尽了,比如Nginx的worker_connections设置过小,或者PHP-FPM的进程数不够。
先别急着给带宽充值,用下面的方法判断。
带宽跑满业务卡顿的排查顺序
第一步:确认是哪个进程在吃带宽
在服务器上执行iftop -i eth0 -P,按“P”键开启端口显示,你会看到一堆连接列表,按流量从高到低排在最前面的就是大流量源,如果某个陌生IP独占了几十Mbps,可能是盗链、爬虫或网络攻击,如果流量分散,每个IP都不高,那就要看下一层。
执行nethogs eth0可以按进程显示带宽占用,能直接看到是

nginx、php-fpm还是mysqld在大量发送数据,这一步能把问题定位到应用层面。
第二步:查看TCP连接状态
执行ss -s,输出里会有estab和time-wait的数量,如果TIME-WAIT数量远高于ESTABLISHED,说明系统里有大量短连接在频繁建立和关闭,建立连接需要TCP三次握手,关闭连接需要四次挥手,每一次握手和挥手都消耗带宽和自己的处理资源,行业共识认为:大量短连接造成的握手开销,比持续传输同样数据量的成本高出3到5倍。
再执行ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn,统计当前并发连接来源IP,如果单个IP的连接数异常高,直接封禁或限流。
第三步:观察CPU和磁盘等待时间
执行top,按“1”看每个核心的使用率,重点看wa(I/O Wait)列,如果这个值超过30%,说明磁盘读写速度已经拖累了整个系统,再执行iostat -x 1,看%util列,接近100%表示磁盘已经忙不过来了。
数据库服务是磁盘IO的消耗大头,如果是MySQL,进入命令行执行SHOW PROCESSLIST;,看有没有大量Copying to tmp table或Sending data状态,这些状态说明查询产生的临时表正在写磁盘,速度自然慢。
第四步:看应用日志中的响应时间
用Nginx做Web服务时,打开access_log,确认日志格式里包含$request_time和$upstream_response_time这两个变量,前者表示整个请求的处理耗时,后者表示请求转发到后端后后端的处理耗时,如果upstream_response_time经常超过2秒,说明业务逻辑或数据库有性能问题,跟带宽没有关系,如果upstream_response_time很快,但request_time很长,瓶颈在传输层面,这时候可以考虑带宽或网络质量。
上面四步做完,基本能得出一个结论:卡顿是从哪个环节开始的。
| 特征 | 带宽瓶颈 | 服务器瓶颈 |
|---|---|---|
| 带宽利用率 | 持续接近上限 | 可能正常或略高 |
| CPU使用率 | 较低 | 较高或频繁波动 |
| 磁盘IO | 无异常 | %util常超60% |
| 用户感知 | 下载慢、图片加载慢 | 点击后白屏,TTFB长 |
| 连接状态 | 大量已完成传输的连接 | 大量等待处理的半连接或锁 |
国内服务器带宽价格对比:升级前想清楚
如果你已经定位到确实是带宽不够用,那也要想清楚怎么升级,国内云服务器带宽计费模式主要分两种:固定带宽和按流量。
固定带宽模式适合流量平稳的业务,例如你买5Mbps带宽,每个月固定费用,超出部分会被限速,这种模式的好处是成本可控,坏处是一旦遇到突发流量就立刻卡死,按流量模式则相反,上限可以设得很高,用多少付多少,平时费用低,但遇到攻击或突发高峰,费用可能让你心疼。
国内主流云厂商的固定带宽定价有一个共性规律:1Mbps到5Mbps的单价比较便宜,从5Mbps往上升,每Mbps的单价会跳涨,如果你只想把带宽从5Mbps升到10Mbps,增加的预算不如用来做优化,业内专家指出:多数情况下,用CDN分流静态资源、开启压缩、限制恶意连接带来的性能提升,比单纯加带宽更明显。
在“国内服务器带宽价格对比”这个决策上,建议你用这样一个原则:如果带宽每月都有几天跑满,按流量计费更划算;如果找不出一段空闲期,那说明业务体量已经把当前带宽用光了,先做架构拆分,再考虑加带宽。
带宽跑满但业务卡顿,先做这几个实操动作
限制单IP并发连接数
对于Nginx,在http块里加:
limit_conn_zone $binary_remote_addr zone=perip:10m;
然后在server块里设置:
limit_conn perip 20;
这样单个IP最多同时建立20个连接,爬虫和多线程下载工具很容易被限制住,带宽压力会迅速缓解,别忘了同时设置请求频率限制:
limit_req_zone $binary_remote_addr zone=peripreq:10m rate=1r/s;
在location里执行:
limit_req zone=peripreq burst=5;
开启HTTP/2和压缩传输
HTTP/2允许多路复用,一个连接里可以同时传多个文件,能大幅减少建立新连接的次数,Nginx配置:

listen 443 ssl http2;
server_name example.com;
同时开启gzip压缩,把文本类资源体积减少一大截:
gzip on;
gzip_types text/plain text/css application/json application/javascript;
有统计显示,开启gzip后,纯文本传输量能压缩50%到80%,图片本身已经不压缩了,别浪费CPU去压图片,除非你有WebP需求。
交给CDN
如果你的网站图片多、视频多,把这些资源迁移到CDN,源站带宽能立刻降下来,但要注意:CDN只能分流静态请求,动态接口仍然要回源,如果源站本身处理慢,CDN也救不了你,只会把卡顿掩盖在缓存层背后。
封禁恶意抓取和攻击流量
执行tail -n 10000 access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20,找出访问次数最多的前20个IP,如果是陌生IP且没有正常的User-Agent,直接加到防火墙黑名单:
iptables -A INPUT -s 1.2.3.4 -j DROP
更好的做法是用fail2ban,它会自动检测高频访问并封禁,封掉一批垃圾流量后,带宽占用可能直接下降30%。
防止带宽再次跑满的长期手段
优化完这次问题,还要防止下次再犯,给服务器配一个带宽监控工具,比如vnstat每五分钟统计一次流量,或者用Prometheus抓取网卡指标,配合Grafana画曲线图,设置告警阈值,比如带宽连续10分钟超过90%,立即通知你。
定期做压测也很重要,用Apache Bench发起并发请求,ab -n 1000 -c 100 https://yourdomain.com,观察响应时间和错误率,如果压测过程中带宽没有跑满但响应时间已经很长,说明瓶颈在应用层,你需要去优化代码或数据库,如果带宽先跑满,那才考虑把连接数和压缩优化做完再升级。
网络架构上,尽量把静态资源、动态接口、数据库拆到不同服务上,同一台服务器既跑Web又跑MySQL,还兼着图片存储,任何一个环节出问题都会互相拖累。
带宽跑满但业务卡顿,先排查连接和响应时间,再决定是否升级带宽。 真正的高性价比路径是:限制无效连接、压缩传输数据、分流静态内容,最后才轮到购买更多带宽。
