香港VPS打开慢怎么优化
来源: 飞翔小编 2026/11/5 23:25:45 浏览量:0
一、打开慢到底慢在哪一段:先测量再动手

香港VPS打开慢,很多人第一反应是「换个配置更高的机器」。这个反应有一半是对的,另一半纯属浪费钱。因为从用户按下回车到页面完全显示,中间被拆成三段完全不同的耗时,每一段的成因和解法都不一样。
第一段是首字节时间(TTFB):从请求发出到服务器返回第一个字节。这段时间花在网络往返、TCP 握手、TLS 握手、排队等 Web 服务器 fork 出 worker、PHP 解释器启动、数据库查询上。这是最容易被误判的一段——很多人看到「打开慢」就以为带宽不够,但带宽只影响第二段。
第二段是传输时间:服务器把 HTML、CSS、JS、图片的字节流给出去。这段由带宽上限和页面总大小共同决定。100Mbps 的口传一个 2MB 的页面,理论满速只需要 0.16 秒;如果你实测花了 5 秒,问题一定不在带宽,而在链路拥塞、服务器上行被邻居抢占,或者页面上有什么东西在拖住下载。
第三段是渲染时间:浏览器拿到数据后解析 HTML、拉取其余静态资源、执行 JavaScript、布局、绘制。这一段跟你的 VPS 一点关系都没有,它取决于前端代码质量和访客的设备与网络。很多「打开慢」的工单真相是:手机 4G 打开一个加载了 3MB 未压缩 JS 的主题,服务器 20ms 就返回了 HTML,但访客等了 8 秒。
所以第一步永远是:分段测量,不要凭感觉。
# 1) 分别测 DNS 解析、TCP 连接、TLS 握手、首字节、总耗时
curl -o /dev/null -s -w "DNS: %{time_namelookup}s TCP: %{time_connect}s TLS: %{time_appconnect}s TTFB: %{time_starttransfer}s TOTAL: %{time_total}s SIZE: %{size_download}B\n" https://你的站点/
# 2) 连续 10 次取中位数,别用单次结果下结论
for i in $(seq 1 10); do
curl -o /dev/null -s -w "%{time_starttransfer} %{time_total} %{size_download}\n" https://你的站点/
done | sort -n | awk '{a[NR]=$0} END {print "中位 TTFB/TOTAL/SIZE:", a[int(NR/2)+1]}'
# 3) 看首屏到底请求了多少个资源、总多大
curl -s https://你的站点/ | wc -c
这三个命令跑完,你手里就有了一张分段账单。如果 TTFB 已经超过 300ms,后面两段的优化收益就极其有限,必须先解决服务端。如果 TTFB 在 50ms 以内而总时长很大,那问题在前端资源,加服务器配置一点用都没有。
二、验收数字:优化前后到底该达到什么标准

没有数字标准的优化等于没优化。「感觉快了一点」不能作为验收依据,因为主观感受会被缓存、页面类型、当时的网络状态带偏。这张表是可以直接拿去用的硬指标:
| 指标 | 合格阈值 | 优秀阈值 | 怎么测 | |
|---|---|---|---|---|
| 首字节 TTFB(动态页) | < 300ms | < 100ms | curl -w "%{time_starttransfer}" |
|
| 首字节 TTFB(静态页) | < 100ms | < 50ms | 同上 | |
| 1MB 静态资源下载 | < 2s | < 800ms | curl -o /dev/null 测大图 |
|
| 首页总资源数 | < 30 个 | < 15 个 | 浏览器开发者工具 Network 面板 | |
| 首页传输总量(未压缩) | < 800KB | < 400KB | `curl -s ... \ | wc -c` |
| 内存使用谷值 | < 15% 物理内存 | < 8% | free -m 看 available 列 |
|
| 磁盘占用率 | < 70% | < 50% | df -h |
|
| 数据库单次查询 | < 50ms | < 20ms | SHOW PROFILE 或 EXPLAIN |
|
| 数据库连接数 | < 内存/256MB | < 内存/512MB | SHOW STATUS LIKE "Threads_connected" |
|
| 慢查询数量 | 每小时 < 10 条 | 0 条 | SHOW GLOBAL STATUS LIKE "Slow_queries" |
内存这一项需要说清楚。Linux 报告的 used 里有一部分是内核用来做文件缓存的,机器看着「快满了」其实还很健康。真正的判断标准是在业务低峰时(通常是凌晨)看 available 那一列。 如果 available 长期低于物理内存的 15%,说明一旦遇到突发流量就没有余量,swap 会开始抖动,表现为「平时没问题,一波高峰就卡死」。
Swap 分区的大小与优先级要单独列出来。 Swap 不是用来当内存用的,它是给突发内存不足兜底的保险丝。给 2GB 内存的机器配 2GB Swap 是合理的;有人配 16GB Swap,结果是把本该立刻报错的内存不足,变成了一场漫长的磁盘写入风暴——请求进来,进程排队等 swap 换页,CPU 显示不忙,但请求全部超时。
# 调整 swap 优先级:默认 60,设置成 10 表示优先使用物理内存
sudo swapon --show
sudo sysctl vm.swappiness=10
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
# 内存健康度:重点看 available,不要看 used
free -m
# 查看当前是否在换页(si=换入,so=换出,两列持续非 0 说明 swap 正在工作)
vmstat 1 60
vm.swappiness=10 是一个常用设置:它让内核优先用物理内存,只在确实需要时才动 swap。默认值 60 偏激进,会让内核更早地开始换页,对 VPS 这种既要跑应用又要留余量的场景不合适。
三、压缩:收益最大、成本最低的一步

压缩通常是你能做的第一件事,收益也是最确定的。 文本类资源(HTML、CSS、JS、JSON、XML)用 gzip 或者 brotli 压缩,体积普遍能降到原来的 20% 到 30%。也就是说,一个 800KB 的首页变成 200KB 左右,传输时间直接降到四分之一。
但压缩不是打开就能用的。 有几个关键点:
第一,要压缩的是文本类型,不是所有类型。 PNG、JPEG、WebP、MP4 这些格式本身就是压缩格式,再压一遍是无效功,而且会额外消耗 CPU。Nginx 的 gzip_types 要显式列出该压的类型,不要用通配符。
第二,压缩会消耗 CPU。 这在低配机器上要小心。gzip 压缩一个 100KB 的页面大约消耗几毫秒 CPU,在 1 核机器上如果 QPS 很高,这个开销会被放大。这时候可以用 gzip_comp_level 降到 4 而不是默认的 6,体积只多 5% 到 8%,但 CPU 开销减半。
第三,压缩需要客户端支持。 浏览器都发 Accept-Encoding: gzip,但爬虫不一定。所以不要把原始文件删掉,让服务器能根据请求头返回压缩版或原始版。
第四,压缩要配 gzip_vary on。 这个头的作用是告诉下游缓存(CDN、反向代理、浏览器)这个资源的响应取决于请求的 Accept-Encoding 头。没有它,缓存节点可能把压缩版和原始版搞混,导致用户拿到乱码或者页面加载失败。
第五,静态资源用长效缓存时,压缩和缓存要一起配。 因为有了 Cache-Control: immutable 的资源会被长期缓存,如果一开始压错了(比如某个文件压缩后有问题),用户会拿着坏缓存很久。所以顺序应该是:先配压缩并验证无误,再加长效缓存。
还有一个容易忽略的收益点:压缩对文本的 CPU 开销,取决于压缩级别。 gzip 的默认级别是 6,压缩比和 CPU 消耗比较均衡。在低配机器上,如果你观察到压缩相关的 CPU 占用明显,把级别降到 4 是个有效的折中——体积只增加 5% 到 8%,但 CPU 开销能减掉接近一半。
# Nginx 压缩配置(放在 http 或 server 块里)
# gzip on;
# gzip_min_length 1k; # 小于 1KB 的不压,压缩收益抵不上开销
# gzip_comp_level 5; # 折中:比默认 6 省 CPU,体积只大一点
# gzip_vary on; # 让缓存正确区分
# gzip_types text/plain text/css application/json application/javascript
# application/xml text/xml image/svg+xml application/wasm;
# 验证压缩是否生效:带 Accept-Encoding 请求,看 Content-Encoding 头
curl -sI -H "Accept-Encoding: gzip" https://你的站点/ | grep -i "content-encoding"
# 对比压缩前后体积
echo "原始: $(curl -s https://你的站点/ | wc -c) 字节"
echo "压缩: $(curl -s -H 'Accept-Encoding: gzip' --compressed https://你的站点/ | wc -c) 字节"
# 找出没被压缩的大文件(这些是最该优化的目标)
for f in $(curl -s https://你的站点/ | grep -oE 'src="[^"]+\.js"|href="[^"]+\.css"' | sed 's/.*="//;s/"//' | head -20); do
RAW=$(curl -s "https://你的站点/$f" | wc -c)
GZ=$(curl -s -H "Accept-Encoding: gzip" --compressed "https://你的站点/$f" | wc -c)
echo "$f 原始 ${RAW}B 压缩后 ${GZ}B"
done
四、缓存:让第二次访问不再打扰服务器

压缩解决传输,缓存解决请求数。一个页面如果 30 个资源每一个都回源,服务器要处理 30 次请求;有了缓存,回源的可能只有 1 次。
缓存分两层,各管各的事。
浏览器缓存由响应头控制。核心是 Cache-Control。对带版本号的静态资源(app.3f2a.js),给一年长缓存是安全的,因为改版会换文件名;对 HTML 页面,必须给 no-cache 或者短缓存,否则用户永远拿到旧页面。
服务端缓存把动态页面的渲染结果缓存起来。常见的几种:Redis 缓存查询结果、OPcache 缓存 PHP 字节码、页面级缓存(Varnish、Nginx 的 proxy_cache、或者 WordPress 页面缓存插件)。这三者解决的是不同层次的问题:OPcache 省的是「PHP 解释代码」的时间,Redis 省的是「数据库查询」的时间,页面缓存省的是「整个渲染流程」的时间。收益从大到小差不多是这个顺序,而配置难度也正好是这个顺序——所以先做 OPcache,它最简单且无风险。
缓存最常见的失败原因是键设计。 键如果没包含所有影响输出的参数,就会出现「A 用户看到 B 用户的缓存」。这是缓存类 bug 里最难查的一类,因为它时有时无。判断缓存键是否正确的方法是:故意用两个不同身份的账号请求同一个 URL,如果返回内容完全一样,就是键缺参数。
另一个常见问题是缓存击穿。 某个热点键在过期的瞬间,大量并发请求同时发现缓存没了,于是同时去查数据库。几百个并发查询打在一个数据库上,数据库直接被打挂,然后更多请求缓存未命中,形成雪崩。 解决办法是给热点键加互斥锁(只让一个请求去回源,其他等待),或者给过期时间加随机抖动(不要所有键同时过期)。
还有一个是缓存雪崩。 如果所有键的过期时间都是整数点(整点、整小时),那么到了整点全部同时失效,数据库承受的冲击和击穿一样。解决办法是过期时间加随机量,比如基础值 3600 秒再加 0 到 600 秒的随机数。
# OPcache 配置(php.ini)
# opcache.enable=1
# opcache.memory_consumption=256 # 2GB 机器设 128,4GB 设 256,8GB+ 设 512
# opcache.max_accelerated_files=20000 # 必须大于 PHP 文件总数
# opcache.validate_timestamps=1 # 生产环境可设 0 并配合 opcache.revalidate_freq
# opcache.revalidate_freq=60
# Nginx 静态资源缓存头
# location ~* \.(jpg|jpeg|png|gif|webp|svg|css|js|woff2)$ {
# expires 30d;
# add_header Cache-Control "public, immutable";
# access_log off;
# }
# 确认缓存命中率(Redis)
redis-cli --no-raw INFO stats | grep keyspace_hits
redis-cli --no-raw INFO stats | grep keyspace_misses
# 计算命中率:命中数 / (命中数 + 未命中数)
关于 Nginx 的 proxy_cache,还要注意缓存键的默认构成。 默认的缓存键只包含协议、主机名和请求 URI,不包含查询字符串。这意味着 /article?id=1 和 /article?id=2 会被当成同一个键,第二个用户看到第一个用户的文章。需要在 proxy_cache_key 里显式加上 $is_args$args。
五、CDN 什么时候用、用哪种回源

CDN 解决的是两件事:静态资源就近分发,以及把突发流量挡在源站之外。但它不解决动态请求的计算和数据往返。
什么时候该上 CDN: 访客分布在中国大陆为主的站点、静态资源占比高(超过七成)、或者遇到过明显的流量峰值。
CDN 回源策略是选型的关键。 常见的几种配置对应完全不同的场景:
默认回源是所有请求都回源,适合动态站点,但那样用 CDN 只省了静态资源的带宽。
回源跟随(跟随客户端协议)是回源时保持客户端用 HTTPS还是 HTTP,避免出现 CDN 到源站这一段被降级。
回源到源站 IP 还是回源到源站域名,决定了 CDN 能不能享受 DNS 解析的容错能力。回源到域名是更稳的做法,因为源站 IP 变化时不需要去 CDN 控制台改配置。
缓存规则决定什么内容缓存多久。这一步配错比不用 CDN 还糟——如果把带用户登录态的页面也缓存了,就会出现 A 用户看到 B 用户页面的严重故障。带 Cookie 的请求、POST 请求、带查询参数且参数影响输出的 URL,都必须设为不缓存。
# 检查 CDN 回源是否正常:多次请求看响应头里的 CDN 标识
for i in 1 2 3; do
curl -sI https://你的域名/ | grep -iE "via|x-cache|age|cf-cache-status|x-swift-cachetime"
done
# 检查缓存是否真的命中:Age 头大于 0 说明是缓存响应
curl -sI https://你的域名/static/app.js | grep -i "age"
# 检查带 Cookie 的请求是否被错误缓存(Age 不应有值且不应返回同一份内容)
curl -sI -H "Cookie: session=abc123" https://你的域名/dashboard | grep -iE "age|set-cookie"
关于香港节点的特别提醒:如果你的主要访客在大陆,CDN 节点能否覆盖到你的访客分布,比服务器本身在哪儿更影响最终速度。一个放在香港的源站配上一个有大陆节点的 CDN,实际体验可能好于香港源站直连,因为 CDN 边缘节点离访客更近。
CDN 也有它自己的成本和副作用,不能无脑上。 第一是缓存命中率不够会变成反向优化——如果回源没配好,每次都回源,CDN 只是在中间多加一跳延迟。第二是静态资源没有版本化,CDN 缓存会让老版本长期滞留,用户拿到旧 JS 是很常见的体验问题。第三是CDN 节点和源站之间的回源带宽会计入你的月流量。
还有一个容易被忽略的点:CDN 不能救动态请求。 如果你的 TTFB 本身是 1 秒,CDN 只能把静态资源的加载变快,整体首屏时间改善有限。先把 TTFB 优化到 300ms 以内,再考虑 CDN,顺序反了就是白花钱。
六、数据库调优:把 2 秒的查询变成 20ms

如果你的 TTFB 高,而 CPU 和内存都很闲,那么时间大概率花在数据库查询上。这是建站类应用最常见的情况,因为数据库查询的耗时随数据量增长,而机器配置增长往往跟不上。
第一步是找出慢查询在哪。 MySQL 默认不开慢查询日志,所以要先打开:
# 在 my.cnf 里设置,然后重启
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/slow.log
# long_query_time = 0.5
# 看当前累计的慢查询数量
mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';"
# 找出耗时最长的 10 条查询
mysql -u root -p -e "SELECT time, LEFT(info, 100) AS 查询 FROM mysql.slow_log ORDER BY time DESC LIMIT 10;"
第二步是看执行计划。 EXPLAIN 是最关键的工具。一条 2 秒的查询,慢的原因通常在这几个地方:
没有索引或者索引失效。 最常见的情况是查询条件走了全表扫描。EXPLAIN 里 type 字段是 ALL 就说明是全表扫描,需要加索引。
索引失效的几种情况:对索引列做了函数运算或类型转换(WHERE DATE(create_time) = '...' 会让索引失效,应该改成范围条件)、隐式类型转换(字符串列用数字查询)、最左前缀不匹配(联合索引 idx(a,b,c) 只查 c 列就用不上)。
数据量大了之后,索引的效果也会衰减。 索引不是万能的,一个有几百万行的表,即使走了索引也可能因为回表开销而变慢。这时候要考虑的是分表或者归档。
第三步是配置连接数。 这个参数配错的次数不低于索引配错的次数。
# 数据库连接数上限:内存/256MB 是一个保守起点,内存/512MB 是激进一点的值
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 看有没有慢查询在堆积
mysql -u root -p -e "SHOW PROCESSLIST;"
# 看锁等待情况
mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | grep -A3 "LATEST DETECTED DEADLOCK"
# 手动分析一条查询的执行计划
mysql -u root -p -e "EXPLAIN SELECT * FROM orders WHERE user_id = 12345 AND status = 'paid';"
一个重要判断:如果你的查询本来就该是快的但实际很慢,先看是不是没走索引;如果是走了索引但数据量太大,那优化手段已经不是加索引能解决的了,要考虑分表、缓存或者改架构。 这两种情况的处理方式完全不同,分不清就会一直做无效优化。
七、Web 服务器与 PHP 进程:并发参数配错了就是慢

TTFB 高、内存还有余量、数据库也不慢,那么时间可能花在了 PHP 进程的管理上。PHP-FPM 的参数配错是「资源看着很闲但请求很慢」的头号原因。
问题出在进程数与内存的匹配上。 PHP-FPM 的 pm.max_children 是同时存在的子进程上限。每个 PHP 进程在处理请求时会占用内存,一个典型的 WordPress 请求可能占用 30MB 到 80MB。如果 max_children 设成 50 而机器只有 2GB 内存,那么并发上来的时候 50 个进程会瞬间把内存吃光,触发 swap,请求全部变慢。 反过来,如果 max_children 设成 5 而机器有 16GB 内存,那机器大半闲置,突发流量来的时候请求在队列里排队。
正确的算法是:可用内存 ÷ 单进程内存 = max_children,然后留 30% 给系统和文件缓存。
另一个常被忽略的参数是 pm.status_path。 PHP-FPM 默认有一个状态页面(/fpm-status 或 /status),能看到当前活跃进程、空闲进程、队列长度。这个页面是诊断并发问题的关键工具——队列长度持续不为零,就说明进程数不够。
三种进程管理模式的区别也要知道。 pm = static 是启动时固定启动 N 个进程,不增减,适合流量稳定的场景;pm = dynamic 是有请求时按需增减,有 min_spare_servers 和 max_spare_servers 控制空闲进程数量;pm = ondemand 是有请求才启动进程,空闲超过设定时间就杀掉,这个模式在流量波动大的场景最省内存,但频繁启停进程会带来额外的 CPU 开销。大多数站点用 dynamic 就够。
还有一个跟内存直接相关的参数是 pm.max_requests。 这个参数的含义是「每个子进程处理多少个请求后被回收重建」。设置它的目的是防止 PHP 进程内部的内存泄漏不断累积——很多 PHP 扩展(比如某些数据库驱动、图片处理库)在特定操作下会泄漏内存,进程跑得越久占的内存越多。设置上限让进程定期回收,是防止「跑几天就变慢、只有重启才好转」这类问题的标准做法。500 是一个常见的起点,具体值可以按你的请求特征调整。
最后是 Nginx 侧的参数。 worker_processes 应该设成 CPU 核心数(auto 可以自动),worker_connections 是每个 worker 能处理的最大连接数。但要注意 worker_connections 不是你能扛并发的真实上限——真正的上限是内存能养活的 PHP 进程数乘以每个进程能处理的请求数。把 worker_connections 调到 65535 但只给 2GB 内存,结果是连接被接受了却拿不到 PHP 进程处理,请求全部超时。
# PHP-FPM 进程池配置(php-fpm.d/www.conf)
# pm = dynamic
# pm.max_children = 16 # 按 内存/单个进程占用/0.7 估算
# pm.start_servers = 4 # 启动时的进程数
# pm.min_spare_servers = 4
# pm.max_spare_servers = 8
# pm.max_requests = 500 # 处理这么多请求后回收,防止内存泄漏累积
# pm.status_path = /fpm-status # 开启状态页面
# 看 PHP-FPM 的实际内存占用(RSS 是关键,不是 VIRT)
ps -eo pid,rss,args | grep php-fpm | awk '{s+=$2} END {printf "PHP-FPM 合计 %.0f MB\n", s/1024}'
# 实时看进程数变化
watch -n 2 "ps aux | grep -c '[p]hp-fpm'"
# 通过状态页看队列(需要在 Nginx 里配 location 转发到 status 路径)
curl -s http://127.0.0.1/fpm-status
# Nginx worker 数量是否匹配 CPU 核心数
nginx -V 2>&1 | grep -o "worker_processes[^;]*"
nproc
八、哪些场景优化收益极低:该换机器或者换线路

有些问题优化解决不了,必须从别的方向入手。这一节写清楚边界。
场景一:TTFB 很低但总时长大,瓶颈在前端资源。 这时优化服务器配置完全无效,因为瓶颈在浏览器和链路。唯一有效的路是压缩加缓存加 CDN,成本接近零。换成更贵的机器不会有任何改善。
场景二:访客主要在大陆,而香港机房的大陆方向线路在晚高峰拥塞。 这时候问题在链路上,不在服务器。优化的方向是换线路类型(CN2 GIA、CMIN2、9929 这类优化线路),不是加 CPU。 这一点必须在买机器之前就问清楚,晚高峰表现是线路质量的核心指标。
场景三:业务需要持续大流量出站(比如每月 10TB 以上)。 靠优化软件省流量的空间有限,必须看套餐的流量额度和超额规则。
场景四:你要跑的是计算密集型任务(视频转码、大规模数据处理、模型推理)。 这类场景的瓶颈是 CPU 算力,优化手段几乎没有,只能升配。但升配前要看清楚是几核机型,因为很多 VPS 卖的是超线程或者共享核心,标称的 4 核在满载时性能可能只有物理 2 核。
场景五:数据库的数据量已经到千万行级别。 这时候单机的查询优化基本到了头,要考虑的是分表、分库、或者用缓存扛住热点查询。继续在单机上加 CPU 加内存的收益是递减的。
场景六:你的站点是纯后台系统,没有公开网页。 这种情况用不着地域优势,多付的溢价换不回任何东西,同时还要承担跨境链路的波动。按 CPU 和内存单价挑最划算的一档即可。
# 判断你的业务到底在哪个象限:先量真实的出站流量和访客分布
cat /proc/net/dev | awk 'NR>2 {split($1,a,":"); printf "%-10s 收 %8.2f GB 发 %8.2f GB\n", a[1], $2/1073741824, $10/1073741824}'
# 按访客 IP 段统计请求分布(取前三段)
sudo awk '{print $1}' /var/log/nginx/access.log | cut -d. -f1,2,3 | sort | uniq -c | sort -rn | head -10
# 看看 CPU 是不是被算力密集任务占满
top -bn1 | head -15
九、常见误区:这几个动作只会更慢

误区一:只加 CPU 不加内存。 PHP 和数据库都是吃内存的,CPU 核数翻倍而内存不变,只会更快地把内存耗光,然后开始 swap,延迟从 50ms 变成 800ms。加内存的边际收益通常大于加 CPU。
误区二:重启大法。 网站一慢就 reboot,这会让 OPcache 清空、数据库连接池重建、所有缓存失效,第一个访问者承担全部冷启动成本。该做的是找到慢的真正原因,而不是重置现场。
误区三:把所有东西都装进同一台机器。 数据库、PHP、邮件服务、爬虫任务挤在一台 2GB 机器上,爬虫把内存吃满,整站跟着倒下。至少把定时任务和邮件发送隔离出去,否则你的爬虫就是你的定时炸弹。
误区四:把 worker_connections 调得很大就以为能扛并发。 这只是把排队从应用层挪到了连接层,文件描述符耗尽时 Nginx 会直接拒绝连接。真正的并发能力取决于内存能养多少 PHP 进程和数据库连接。
误区五:以为开了缓存就万事大吉,从不清缓存。 缓存不失效,就永远不知道它是不是还在正常工作。每次发版后手动清一次缓存,并检查命中率——如果清完立刻掉到 50% 以下,说明缓存键设计有问题。
误区六:拿单次测速结果下结论。 网络有抖动,凌晨和晚高峰的结果可能差一倍。每个指标至少测 10 次取中位数,且要分别在工作时段和晚高峰各测一轮。
误区七:开 gzip 但没开 gzip_vary,也不排除已压缩类型。 结果是缓存节点存了一份压缩版、一份原始版,缓存命中率直接减半。
按你的情况,下一步该看哪家
上面讲的是判断标准,但多数人最后还是想问一句「那我该买谁」。按你的实际情况对照下面几条,直接去看对应的机型页比继续比价更快:
- 只想搭个站、预算优先:先看价格最低那档够不够用,别为用不上的配置付钱。看 数脉科技 当前机型与价格
- 做跨境或店群、需要多 IP:优先看 IP 类型与换 IP 政策,别只看配置。看 野草云 当前机型与价格
- 主要访客在国内、在意打开速度:先确认回程线路,再谈配置。看 isvoro 当前机型与价格
价格与库存以商家页面当日显示为准,下单前建议先确认退款窗口与是否支持按月付费。
十、常见问题

香港VPS打开慢,换个更高配置的机器能解决吗? 不能一概而论。先按第一节的方法分段测量:如果 TTFB 已经低于 100ms 而总时长很大,瓶颈在页面体积和前端资源,升配完全无效,做压缩和缓存才是正解;只有当 TTFB 超过 300ms 且内存谷值超过 40% 时,升配才值得考虑。反过来说,盲目升配最常见的结局是花了钱,TTFB 一点没变。
用 CDN 之后香港VPS还有意义吗? 有,但意义变了。CDN 解决的是静态资源就近分发和抗波动,不解决动态请求的计算和数据往返。如果你的业务是动态 API 或登录态页面,源站仍然必须是离用户近的机房,CDN 只是把静态部分卸走。香港节点对华南和华东方向的动态请求仍然有地理优势。
开启 Gzip 会不会影响 SEO? 不会。搜索引擎的爬虫能正常处理 gzip 传输的内容,主流爬虫都支持 Accept-Encoding: gzip。需要注意的是不要对图片和已经压缩过的格式(PNG、JPEG、WebP、MP4)再压缩,那些是无效功。
OPcache 的内存设置多少合适? 2GB 内存机器设 128MB,4GB 设 256MB,8GB 及以上设 512MB。判断依据是 opcache.memory_consumption 配的值加上实际占用不会超过总内存的 15%,并且 opcache.max_accelerated_files 要大于你所有 PHP 文件的总数,否则部分文件不会被缓存。
慢查询日志开多大算合适? long_query_time 设 0.5 秒是一个好起点——比这更短的查询通常不是体验瓶颈。日志文件会增长,注意配置轮转,否则几百 MB 的日志文件本身会拖慢磁盘 IO。
怎么知道优化到底有没有效果? 建立基线、优化、再测,两次都用同一套命令、同一个时段、至少 10 次取中位数。把 TTFB、页面总大小、资源数、内存谷值这四个数记成一张表前后对比。没有基线的优化等于没有优化,因为你会分不清是优化起效还是网络恰好顺畅。
香港VPS的线路应该怎么选才不慢? 这要看你访客的分布。主要访客在大陆方向的,优先看优化线路类型(CN2 GIA、CMIN2、9929 这类),普通国际线路在晚高峰的抖动会很明显;访客主要在港澳台或者东南亚方向的,普通 BGP 线路通常够用。 具体线路类型和报价以官网当日报价为准,问的时候一定要问「晚高峰 20 点到 23 点的实际表现」,而不是只看标称带宽。
Windows 建站和 Linux 建站优化思路一样吗? 差别不大,但具体命令不同。本文给的 Nginx、PHP-FPM、MySQL 命令都是 Linux 下的;Windows 上的 IIS + PHP 或 Windows + Nginx 组合,思路一致(压缩、缓存头、OPcache、数据库索引这四条完全通用),但需要换成对应的 Windows 工具,且文件描述符与进程管理的概念在 Windows 上不适用。
