事情本身不复杂,线索都在日志里。站点按地区显示不同货币,PHP 在每个请求开头同步读一次 GeoIP 的 mmdb 文件。CrUX 里 TTFB 分位数 2.3 秒,移动网络下更差,LCP 全部被拖到 4 秒以上。
第一反应是「地区判断只用于货币展示,却阻塞了整个页面渲染」,验证下来不成立。
原因不止一个,得分开看。GeoIP 查询放在应用层同步执行,没有缓存结果。少数情况下是每次请求都重新打开 mmdb 文件,磁盘 IO 被放大。
另外,mmdb 文件放在网络挂载盘上 每次读取都要走一次网络往返。
先分段测一下服务端耗时
curl -s -o /dev/null -w 'dns:%{time_namelookup} conn:%{time_connect} ttfb:%{time_starttransfer}\n' https://www.example.com/
随后把地区判断交给边缘节点加头
proxy_set_header X-Country $geoip2_data_country_code;
应用层读头并缓存结果
$c = $_SERVER['HTTP_X_COUNTRY'] ?? 'CN';
复测首字节时间
ab -n 100 -c 10 https://www.example.com/ | grep 'Time per request'
恢复的判定其实很直接。改由边缘判断后 TTFB 从 2.3 秒降到 0.28 秒,移动端 LCP 落到 2.4 秒以内,体验分提升 14 分。
补一句。首字节时间里每多一次同步 IO 都会被放大到大流量上,能前置到边缘的判断不要留到应用层做。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
