你的服务器到底能扛多少流量?
这是每个个人站长心里都应该有数、却几乎没人认真算过的一个问题:我现在的服务器配置,到底能扛多少并发?能扛多少 QPS?什么时候需要升级?很多人的做法是"坏了再说"——直到某天文章上了热门、或者被某个大 V 转发,服务器瞬间打满、数据库连接耗尽、站点 502,等抢救过来流量也跑光了。
容量规划不是运维大厂的专利,个人站长同样需要。它的核心就一件事:在流量高峰到来之前,用压测工具测出当前配置的真实上限,然后据此决定是优化代码、加缓存,还是升级硬件。这篇文章把压测和容量规划的完整方法讲清楚,用 wrk、ab 这些免费工具,帮你算出自己站点的真实天花板。
第一步:先分清几个最容易被混淆的指标
谈容量之前,必须先把几个概念理清楚,否则测出来的数据根本没法解读。
QPS(Query Per Second)是每秒处理的请求数,也叫 RPS。它衡量的是"吞吐量",也就是单位时间内你的服务器能处理多少个请求。
并发数(Concurrency)是同一时刻正在处理中的请求数量。它不等于 QPS,两者的关系近似为:QPS ≈ 并发数 ÷ 平均响应时间。举个例子,如果每个请求平均耗时 100 毫秒,你同时处理 10 个请求,那 QPS 就是 10 ÷ 0.1 = 100。这个公式是容量估算的核心。
响应时间(Latency)是单个请求从发出到返回的耗时,通常看平均值、P95(95% 的请求快于这个值)、P99。压测最该关注的是 P95 和 P99,而不是平均值——平均值会被大量快速请求拉低,掩盖住那些慢到让用户想关页面的请求。
还有一个常被忽略的指标是"错误率"。压测时即使 QPS 上去了,如果错误率同时飙升(大量 502、超时),那这个 QPS 是虚的,不能算作容量。
第二步:确定你的真实场景——是静态还是动态
压测前必须先明确自己测的是什么。不同类型页面的承载能力天差地别。
纯静态页面(HTML、图片、CSS)由 Nginx 直接读文件返回,性能极高,一台 1 核 1G 的小机器轻松扛几千 QPS。动态页面(PHP + MySQL 查询)每处理一个请求都要跑代码、连数据库,性能低一到两个数量级,可能只有几十到几百 QPS。
你的站点是哪种类型,压测的目标就完全不同。而且真实流量从来不是均匀的:访问首页、列表页、文章页、搜索页的比例各不相同,其中搜索页往往最耗资源。所以压测时应该分别测这几类页面的典型 URL,而不是只压一个首页就下结论。
更重要的是,要区分"缓存命中"和"缓存未命中"两种情况。如果你用了 Nginx 缓存、Redis 缓存或页面静态化,那么缓存命中的请求几乎不碰数据库,性能接近静态页;CPU 和数据库的压力只集中在缓存未命中的那部分请求上。所以压测时要单独测"缓存全开"和"缓存全关"两种状态,前者代表稳态容量,后者代表极端情况(缓存刚清空、大量新内容被同时抓取)下的容量。
第三步:用 wrk 做压测(推荐)
压测工具里,ab(ApacheBench)最简单但功能弱,wrk 性能强、支持多线程、报告详细,是个人站长的首选。安装很简单:
apt-get install -y wrk
# 若源里没有 wrk,从源码编译
git clone https://github.com/wg/wrk
cd wrk && make && cp wrk /usr/local/bin/基本用法是这样的:
# 用 4 个线程、100 个连接,持续压测 30 秒
wrk -t4 -c100 -d30s https://example.com/article/123.html参数含义:-t 是线程数(一般设成 CPU 核数),-c 是并发连接数,-d 是持续时长。wrk 会输出类似这样的结果:
Running 30s test @ https://example.com/article/123.html
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 45.21ms 12.30ms 320.00ms 88.5%
Req/Sec 580.30 65.20 720.00 70.0%
69720 requests in 30.10s, 812.50MB read
Requests/sec: 2316.28
Transfer/sec: 27.00MB解读:Requests/sec 就是 QPS,这里约 2316;Latency 平均 45 毫秒;Max 是最大延迟 320 毫秒。这里有个重要的观察方法:如果平均延迟随着并发数增加而明显上升,说明服务器已经开始排队了。你可以做一组阶梯测试,用 -c10、-c50、-c100、-c200 分别压测,观察 QPS 和延迟的变化。当并发数再增加、QPS 却不再上升而延迟急剧增加时,那个拐点就是你的"饱和点",也就是真实容量上限。
还想测 POST 请求或带认证头的场景,可以用 Lua 脚本扩展 wrk。-t 的线程数不是越大越好,超过 CPU 核数反而会因上下文切换降低性能。
第四步:压测时的正确姿势和常见陷阱
压测有几个经典陷阱,踩了一个,测出来的数据就完全不可信。
陷阱一:压测机和被测服务器在同一台机器上。这样压测工具本身和被测服务抢 CPU,测出来的数字严重偏低。正确做法是用一台独立的机器(哪怕是你另一台 VPS)作为压测源,通过公网压测你的目标服务器。
陷阱二:忽略了网络带宽瓶颈。如果压测机到服务器的带宽只有 10Mbps,而你压的页面又比较大,那瓶颈就是带宽而不是服务器性能。压测时观察服务器的网卡流量,如果带宽跑满了,那测出来的是带宽上限,不是 CPU 上限。
陷阱三:只压不改,测完就完。压测的目的是发现问题并优化。所以压测过程中要同时用 top、htop 看 CPU、用 iostat 看磁盘 I/O、用 mysqladmin processlist 看数据库连接数、用 netstat -an | grep :80 | wc -l 看连接状态。这样才能知道瓶颈到底在 CPU、内存、磁盘还是数据库连接上。
陷阱四:在生产服务器上直接压测。压测会打满服务器,可能影响真实用户访问,甚至触发云服务商的 DDoS 防护把你 IP 封了。应该在测试环境压测,或者选在半夜流量最低的时段。另外,很多云厂商明确禁止对公网 IP 做压测,压测前一定看清条款,必要时用内网 IP 压测。
第五步:压测之外——用监控数据推算真实容量
压测测的是"理论极限",但真实容量还要结合日常监控数据看。如果你的站点已经在运行,可以从这些数据推算:观察一周内的流量曲线,找到峰值时段的 QPS(比如从 Nginx access log 里统计每秒请求数),再看那个时段服务器的 CPU、内存、连接数的实际占用。如果峰值时 CPU 到了 60%,说明还有余量;如果到了 90% 以上,那下一次流量翻倍就是宕机。
从 Nginx 日志统计 QPS 的方法:
# 统计某天每秒钟的请求数,取最大的一秒
awk '{print $4}' /var/log/nginx/access.log \
| cut -d: -f1-3 \
| sort | uniq -c | sort -rn | head -5这段命令把所有请求按"秒"聚合,输出请求数最多的前 5 秒,这就是你的真实峰值 QPS。用这个峰值和压测得到的饱和点对比,就能算出当前配置的"安全余量"。经验法则是留 2 到 3 倍余量,也就是说如果峰值 QPS 是 500,那你希望服务器能扛 1000 到 1500,才不至于一次小爆款就把站点打挂。
第六步:容量不够时的优化顺序
测出容量不够之后,先别急着升级硬件。升级硬件是最贵的手段,很多时候同样的预算花在优化上效果更好。推荐的优化顺序是:
第一,上缓存。这是性价比最高的一招。给页面加 Nginx 缓存或 Redis 缓存,让绝大多数请求不碰数据库,容量往往能提升几倍到几十倍。很多站点"扛不住",根源就是每个请求都去查数据库。
第二,优化数据库。加索引、优化慢查询、减少不必要的查询。一条慢查询可能拖垮整个数据库,加了索引后 QPS 可能直接翻倍。用 SHOW PROCESSLIST 和慢查询日志找出耗时最长的那几条,优先处理。
第三,调整 Web 服务器和 PHP 的进程数。Nginx 的 worker_processes、PHP-FPM 的 pm.max_children 要根据内存合理设置。php-fpm 进程数设得太大反而会因为内存不足触发 OOM,设得太小则并发上不去。估算方法是:pm.max_children = 可用内存 ÷ 单进程内存占用。
第四,静态资源分离。把图片、CSS、JS 放到 CDN 或独立的静态服务器上,主服务器只处理动态请求,能显著降低主服务器的压力和带宽占用。
第五,最后才是升级硬件。到这一步说明前面的优化都已经做到位了,升级 CPU 和内存能带来线性的容量提升。
真实案例:一次压测发现的两个致命瓶颈
我压测过一个站长的 Typecho 博客,配置是 2 核 4G 的 VPS。他抱怨说一有人转发文章,站点就 502。我用独立的机器对他压测,静态页面测得大约 3000 QPS,看起来还行。但一压文章详情页(动态 PHP + MySQL),QPS 直接掉到 60 左右,而且延迟从 50 毫秒飙到 2 秒。
压测的同时我看服务器监控,发现两根曲线同时爆表:一个是 MySQL 的 CPU 占用冲到 100%,另一个是 PHP-FPM 的进程数瞬间打满、开始排队。进数据库一查慢查询日志,发现文章页每次加载都执行了一条没有走索引的 SELECT ... WHERE keywords LIKE '%...%' 的模糊查询(用来做"相关文章"推荐),这条查询在全表几万行的数据上每次要扫几秒。
修复分两步。第一步,给相关文章推荐改成基于标签的精确匹配并加了复合索引,那条慢查询从 2 秒降到 5 毫秒。第二步,给文章页加了 Nginx 页面缓存,缓存命中时完全不碰 PHP 和数据库。改完再压测,动态页面 QPS 从 60 提升到大约 1500(缓存命中场景),峰值时段的 CPU 占用从 100% 降到 30% 以下。这个案例说明:压测的真正价值不是得到一个 QPS 数字,而是通过压测同时看监控、定位瓶颈。不结合监控的压测,只是跑了个寂寞。
第七步:把容量规划变成日常习惯
容量规划不是一次性任务。建议你每季度做一次,或者在预计有大流量事件(上新内容、做活动、上热门)之前做一次。日常可以用一个简单的定时脚本,每天统计前一天的峰值 QPS 和峰值时的资源占用,记录下来形成趋势。当趋势显示峰值资源占用在持续逼近上限时,就是该优化的信号了。
另外,准备一个"降级预案":当流量突然涌入、服务器扛不住时,可以快速关闭非核心功能(比如相关文章推荐、评论、搜索),优先保证文章页能打开。这个预案要提前演练,别等真出事才手忙脚乱地找开关。
总结
容量规划的核心逻辑是:先用压测工具测出当前配置的真实饱和点,再结合日常监控的峰值数据,判断还有多少余量,据此决定优化还是升级。压测要用独立机器、要同时看监控、要测多种页面类型和缓存状态,还要注意别在生产环境乱压。容量不够时,优化顺序是缓存优先、数据库次之、Web 进程第三、静态分离第四,硬件升级放最后。
对个人站长来说,你不需要像大厂那样做精细的容量模型,但你必须知道:我的站点能扛多少并发,峰值时资源占用多少,什么时候会到极限。心里有这三个数字,你就能在流量来的时候从容应对,而不是看着 502 页面干着急。这篇文章里的 wrk 压测方法、Nginx 日志 QPS 统计命令、优化顺序,都可以直接拿去用,建议你今天就在自己的服务器上跑一遍,摸清自己的真实家底。