[{"data":1,"prerenderedAt":474},["ShallowReactive",2],{"blog-ttfb-network-vs-server":3,"blog-prev-ttfb-network-vs-server":138,"blog-next-ttfb-network-vs-server":374},{"id":4,"title":5,"author":6,"body":7,"canonical":122,"category":123,"cover":122,"date":124,"description":125,"draft":126,"extension":127,"keywords":122,"meta":128,"navigation":129,"noindex":126,"ogImage":122,"path":130,"seo":131,"seoDescription":122,"seoTitle":122,"stem":132,"tags":133,"updated":122,"__hash__":137},"blog\u002Fblog\u002Fttfb-network-vs-server.md","TTFB 高先分清是网络还是服务端，别急着换机房","元析智能",{"type":8,"value":9,"toc":114},"minimark",[10,14,17,56,62,67,70,73,77,80,83,86,89,92,95,98,101,104,107,110],[11,12,13],"p",{},"TTFB 高的时候，先别换机房。今年 1 月我们查过一个 SaaS 的首页，移动端首字节 1.4 秒，团队第一反应是\"服务器不行\"，准备换云厂商。查下来 800 毫秒花在服务端自己身上，换到哪儿都一样。",[11,15,16],{},"先把 TTFB 拆开看。用 curl 的耗时分解，一个请求能拆成五段：",[18,19,24],"pre",{"className":20,"code":21,"language":22,"meta":23,"style":23},"language-bash shiki shiki-themes github-light github-dark","curl -o \u002Fdev\u002Fnull -s -w \"dns:%{time_namelookup} tcp:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer}\\n\" https:\u002F\u002Fexample.com\u002F\n","bash","",[25,26,27],"code",{"__ignoreMap":23},[28,29,32,36,40,44,47,50,53],"span",{"class":30,"line":31},"line",1,[28,33,35],{"class":34},"sScJk","curl",[28,37,39],{"class":38},"sj4cs"," -o",[28,41,43],{"class":42},"sZZnC"," \u002Fdev\u002Fnull",[28,45,46],{"class":38}," -s",[28,48,49],{"class":38}," -w",[28,51,52],{"class":42}," \"dns:%{time_namelookup} tcp:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer}\\n\"",[28,54,55],{"class":42}," https:\u002F\u002Fexample.com\u002F\n",[11,57,58,61],{},[25,59,60],{},"time_starttransfer"," 减去前面几段，剩下的才是服务端处理时间。这个站 DNS 30 毫秒、TLS 120 毫秒、传输 90 毫秒，剩下 800 毫秒就是后端在算。",[63,64,66],"h2",{"id":65},"服务端那-800-毫秒在干什么","服务端那 800 毫秒在干什么",[11,68,69],{},"那个站一次页面请求串行调了 6 个接口，最慢的一个 340 毫秒。6 个加起来 1.1 秒，有并发，实际 800 毫秒。前端一直以为是网络问题，因为监控上只看到\"页面慢\"三个字。",[11,71,72],{},"查法是看应用侧的链路追踪，或者最土的办法：在服务端入口加时间日志，记每个接口的耗时。这个客户加完日志第二天就定位了，比讨论一周有用。",[63,74,76],{"id":75},"改法能并行的并行能缓存的缓存","改法：能并行的并行，能缓存的缓存",[11,78,79],{},"我们做了两件事：6 个接口里 4 个改成并行，总耗时从 800 降到 260 毫秒；首页那块\"最新公告\"从实时查库改成 60 秒缓存。TTFB 从 1.4 秒降到 480 毫秒，同一批机器。",[63,81,82],{"id":82},"什么情况才该怀疑网络",[11,84,85],{},"三种情况我才会建议查链路：TTFB 在 200 到 400 毫秒之间但各地差异大；静态资源也慢；TLS 握手占 300 毫秒以上。这三种通常指向线路或者 CDN 节点问题，和服务端代码无关。",[11,87,88],{},"还有个粗糙但好用的判断：如果你的静态 HTML 的 TTFB 就很高，那是基础设施；如果只有动态页慢，那基本是代码。这个判断一分钟能做完，比开会讨论有用。",[63,90,91],{"id":91},"一个容易误判的情况",[11,93,94],{},"首页慢、产品页快，这种情况很常见，因为首页的接口最多。我们查过一个站，产品页 TTFB 210 毫秒，首页 1.3 秒，团队按首页的平均值去投诉机房，方向完全错了。",[11,96,97],{},"正确做法是按页面类型分组统计 TTFB，每种取 P75。营销页、文档页、后台页分开看，差异往往比你想的大。",[63,99,100],{"id":100},"我们给客户的检查顺序",[11,102,103],{},"第一步，挑三个页面（首页、一个产品页、一个文档页）用 curl 各跑五次，记下五段耗时。第二步，把服务端那一段和接口日志对上。第三步，才决定是改代码、加缓存还是查线路。",[11,105,106],{},"这个顺序的好处是成本低。三步做完，半小时，能排除八成误判。最怕的是先入为主地认为是网络问题，换了一圈机房，最后发现是接口没并行。",[11,108,109],{},"最后一句：换机房是成本最高、见效最不确定的一招。我们接手过的性能项目里，真正靠换机房解决问题的只有两次，都是国内单线机房那种情况。",[111,112,113],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":23,"searchDepth":115,"depth":115,"links":116},2,[117,118,119,120,121],{"id":65,"depth":115,"text":66},{"id":75,"depth":115,"text":76},{"id":82,"depth":115,"text":82},{"id":91,"depth":115,"text":91},{"id":100,"depth":115,"text":100},null,"技术SEO","2025-12-14","一个 SaaS 首页移动端首字节 1.4 秒，团队准备换云厂商，其实 800 毫秒花在服务端串行接口上。给一条 curl 拆时间的命令，和三个才该怀疑网络的情况。",false,"md",{},true,"\u002Fblog\u002Fttfb-network-vs-server",{"title":5,"description":125},"blog\u002Fttfb-network-vs-server",[134,135,136],"TTFB","服务端性能","性能诊断","BR70gBacE8JBbLjWfYgmkRwPIixD9DwNRj0tqZXvyIE",{"id":139,"title":140,"author":6,"body":141,"canonical":122,"category":123,"cover":122,"date":363,"description":364,"draft":126,"extension":127,"keywords":122,"meta":365,"navigation":129,"noindex":126,"ogImage":122,"path":366,"seo":367,"seoDescription":122,"seoTitle":122,"stem":368,"tags":369,"updated":122,"__hash__":373},"blog\u002Fblog\u002Fcrawl-log-analysis-commands.md","日志分析入门：三个命令看蜘蛛在抓什么",{"type":8,"value":142,"toc":355},[143,146,150,212,215,219,256,259,263,318,321,328,331,334,337,340,343,346,349,352],[11,144,145],{},"日志是唯一能直接看到蜘蛛行为的数据。GSC 的抓取统计只给汇总，百度搜索资源平台给得更少。要看细节，还是得自己读 access.log。",[63,147,149],{"id":148},"命令一数请求","命令一：数请求",[18,151,153],{"className":20,"code":152,"language":22,"meta":23,"style":23},"grep -c \"Googlebot\" access.log\ngrep \"Googlebot\" access.log | awk '{print $4}' | cut -d: -f1 | sort | uniq -c\n",[25,154,155,169],{"__ignoreMap":23},[28,156,157,160,163,166],{"class":30,"line":31},[28,158,159],{"class":34},"grep",[28,161,162],{"class":38}," -c",[28,164,165],{"class":42}," \"Googlebot\"",[28,167,168],{"class":42}," access.log\n",[28,170,171,173,175,178,182,185,188,190,193,196,199,201,204,206,209],{"class":30,"line":115},[28,172,159],{"class":34},[28,174,165],{"class":42},[28,176,177],{"class":42}," access.log",[28,179,181],{"class":180},"szBVR"," |",[28,183,184],{"class":34}," awk",[28,186,187],{"class":42}," '{print $4}'",[28,189,181],{"class":180},[28,191,192],{"class":34}," cut",[28,194,195],{"class":38}," -d:",[28,197,198],{"class":38}," -f1",[28,200,181],{"class":180},[28,202,203],{"class":34}," sort",[28,205,181],{"class":180},[28,207,208],{"class":34}," uniq",[28,210,211],{"class":38}," -c\n",[11,213,214],{},"第一条看总量，第二条按天分组看趋势。我们习惯把百度蜘蛛（Baiduspider）也一起数，两条曲线放一起看，一边涨一边跌通常意味着抓取预算被某个方向吃掉了。",[63,216,218],{"id":217},"命令二看状态码分布","命令二：看状态码分布",[18,220,222],{"className":20,"code":221,"language":22,"meta":23,"style":23},"grep \"Googlebot\" access.log | awk '{print $9}' | sort | uniq -c | sort -rn\n",[25,223,224],{"__ignoreMap":23},[28,225,226,228,230,232,234,236,239,241,243,245,247,249,251,253],{"class":30,"line":31},[28,227,159],{"class":34},[28,229,165],{"class":42},[28,231,177],{"class":42},[28,233,181],{"class":180},[28,235,184],{"class":34},[28,237,238],{"class":42}," '{print $9}'",[28,240,181],{"class":180},[28,242,203],{"class":34},[28,244,181],{"class":180},[28,246,208],{"class":34},[28,248,162],{"class":38},[28,250,181],{"class":180},[28,252,203],{"class":34},[28,254,255],{"class":38}," -rn\n",[11,257,258],{},"健康站点 200 占 85% 以上，5xx 应该低于 0.5%。404 占比高说明死链多，301 占比高说明重定向链没收敛。5xx 是最要命的，蜘蛛连续遇到几次服务端错误会主动降频。",[63,260,262],{"id":261},"命令三按路径聚合","命令三：按路径聚合",[18,264,266],{"className":20,"code":265,"language":22,"meta":23,"style":23},"grep \"Googlebot\" access.log | awk '{print $7}' | cut -d\u002F -f2 | sort | uniq -c | sort -rn | head -20\n",[25,267,268],{"__ignoreMap":23},[28,269,270,272,274,276,278,280,283,285,287,290,293,295,297,299,301,303,305,307,310,312,315],{"class":30,"line":31},[28,271,159],{"class":34},[28,273,165],{"class":42},[28,275,177],{"class":42},[28,277,181],{"class":180},[28,279,184],{"class":34},[28,281,282],{"class":42}," '{print $7}'",[28,284,181],{"class":180},[28,286,192],{"class":34},[28,288,289],{"class":38}," -d\u002F",[28,291,292],{"class":38}," -f2",[28,294,181],{"class":180},[28,296,203],{"class":34},[28,298,181],{"class":180},[28,300,208],{"class":34},[28,302,162],{"class":38},[28,304,181],{"class":180},[28,306,203],{"class":34},[28,308,309],{"class":38}," -rn",[28,311,181],{"class":180},[28,313,314],{"class":34}," head",[28,316,317],{"class":38}," -20\n",[11,319,320],{},"看哪个一级路径吃掉最多请求。2025 年 10 月一个站日抓 1.2 万次，排第一的是 \u002Fapi\u002F，占 41%，全部返回 401。robots.txt 里没屏蔽 API 路径，蜘蛛每天白跑 5000 次。屏蔽后产品页的抓取从每天 800 次涨到 2600 次。",[11,322,323,324,327],{},"顺手还能算响应时间：把 ",[25,325,326],{},"$request_time"," 聚合一下，平均超过 1 秒就要查服务器，蜘蛛抓取频次和响应速度强相关。",[63,329,330],{"id":330},"日志怎么留",[11,332,333],{},"nginx 默认按天切分，保留 7 天，做抓取分析不够用。我们一般让运维保留 90 天并压缩归档，或者直接推到日志服务里。做一次完整诊断要看连续 4 周的数据，单看一天容易被大促、发版这种异常带偏。",[11,335,336],{},"如果站点在 CDN 后面，源站日志里只有回源请求，蜘蛛直接命中缓存的请求看不到。这种情况要用 CDN 厂商的访问日志，或者把蜘蛛 UA 的回源规则调整一下。我们遇到过一次，客户以为自己日抓只有 300 次，换到 CDN 日志一看实际是 4000 次，诊断结论完全反了。",[63,338,339],{"id":339},"三个常见误判",[11,341,342],{},"把 UA 当身份。UA 可以伪造，日志里出现自称 Googlebot 的请求不一定是真的，验证方法是反查 IP 段。把缓存命中当没抓。前面说过，CDN 后面的日志会少一大截。把周末的低抓取当异常。蜘蛛也有自己的节奏，按周看比按天看稳。",[63,344,345],{"id":345},"什么时候不用做",[11,347,348],{},"日抓取量 1000 次以下的站，先别碰日志分析。抓取量太小，结论全是噪声，先把内容做起来、把收录问题修好。抓取预算这件事，是流量上来了才值得抠的细节。",[11,350,351],{},"工具方面，GoAccess 能出一份可视化报表，Screaming Frog Log File Analyser 适合和爬虫数据对照，命令行足够应付 80% 的场景。我们做诊断先用三个命令看一遍，判断要不要上工具。",[111,353,354],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":23,"searchDepth":115,"depth":115,"links":356},[357,358,359,360,361,362],{"id":148,"depth":115,"text":149},{"id":217,"depth":115,"text":218},{"id":261,"depth":115,"text":262},{"id":330,"depth":115,"text":330},{"id":339,"depth":115,"text":339},{"id":345,"depth":115,"text":345},"2025-12-13","不用装工具也能做日志分析。我们用 awk 和 grep 从 nginx 日志里拉出蜘蛛请求量、状态码分布和最费预算的路径，附一个 2025 年 10 月的诊断记录，日抓 1.2 万次里 41% 是无效请求。",{},"\u002Fblog\u002Fcrawl-log-analysis-commands",{"title":140,"description":364},"blog\u002Fcrawl-log-analysis-commands",[370,371,372],"日志分析","抓取预算","爬虫","0jXqh1Xu0qIIJacHBvtC-GCTZ9P3T1s6qFtljpRgYHs",{"id":375,"title":376,"author":6,"body":377,"canonical":122,"category":462,"cover":122,"date":463,"description":464,"draft":126,"extension":127,"keywords":122,"meta":465,"navigation":129,"noindex":126,"ogImage":122,"path":466,"seo":467,"seoDescription":122,"seoTitle":122,"stem":468,"tags":469,"updated":122,"__hash__":473},"blog\u002Fblog\u002Fmonthly-content-review-metrics.md","月度内容复盘只看四个数，其他都是自娱自乐",{"type":8,"value":378,"toc":452},[379,382,385,388,391,394,397,400,403,406,409,412,415,418,422,425,428,431,434,437,440,443,446,449],[11,380,381],{},"我们给客户做月度内容复盘，只放四个数：曝光、点击率、滚动到 75% 的比例、内容带来的注册或咨询。平均排名、字数、发文篇数都不进表。不是这些数没意义，是看了也做不出下一个动作。",[63,383,384],{"id":384},"四个数分别说明什么",[11,386,387],{},"曝光说明选题有没有被搜到，点击率说明标题和描述有没有让人想点，滚动深度说明内容有没有兑现点击，转化数说明这篇有没有商业价值。",[11,389,390],{},"四个数串起来就是一条链路，哪一段断了，下个月的活就往哪儿派。",[63,392,393],{"id":393},"平均排名为什么被砍掉",[11,395,396],{},"平均排名是按曝光加权摊平的一个数。加了 200 个长尾曝光，平均排名会变好看，但一篇都没进前 20。",[11,398,399],{},"2025 年 10 月我们给一个客户做复盘，平均排名从 18 涨到 14，客户挺高兴。我翻到查询级数据，发现进前 10 的查询只多了 2 个。那个月真正变好的是曝光，排名只是被平均出来的。",[63,401,402],{"id":402},"点击率是最被低估的数",[11,404,405],{},"同样排第 5，点击率 1.5% 和 3% 是两倍流量差距。改标题和描述的成本，比写一篇新文章低十倍。",[11,407,408],{},"2025 年 11 月我们给一个开发者工具站改了 12 个页面的标题和描述，只调整了把结论提前和加上数字，一个月后这些页面点击率从 1.8% 到 3.1%，曝光基本没变。",[63,410,411],{"id":411},"转化数怎么归因才不算错",[11,413,414],{},"最后点击归因会把内容的价值算给品牌词和首页，内容看起来毫无贡献。我们的做法是加一个“内容首触”标记：用户第一次进来是内容页，90 天内成交都算这篇内容一份。",[11,416,417],{},"这个标记要在 GA4 里配，配一次能用一年，比每月解释数据便宜。",[63,419,421],{"id":420},"复盘会开-30-分钟","复盘会开 30 分钟",[11,423,424],{},"前 10 分钟看四个数，中间 10 分钟挑出两个变差的页面，最后 10 分钟定下个月的三个动作。定不出动作的复盘就是汇报，不叫复盘。",[63,426,427],{"id":427},"还有一个数我们单独看",[11,429,430],{},"AI 引用次数。每月手工查 20 个目标问题，记录有没有被引用。这个数不进月度表，季度看一次，因为波动太大。",[63,432,433],{"id":433},"数据不对齐怎么处理",[11,435,436],{},"客户的 GA4、搜索后台、表单后台三个数经常差 20% 以上。别在复盘会上解释差异，先把口径固定下来：曝光和点击只认搜索后台，转化只认表单和 CRM。",[11,438,439],{},"差异留给月报附录，一句话说明。把时间花在解释差异上，复盘会就变成了对账会。",[63,441,442],{"id":442},"一个我们停掉的动作",[11,444,445],{},"以前每月会统计“发了多少篇”“总字数多少”。这两个数除了自我安慰没有用途，2025 年 6 月停掉之后，复盘会省了 15 分钟。",[11,447,448],{},"填表的人也不必为了好看硬凑篇数，内容质量反而稳了。",[11,450,451],{},"复盘不是汇报，是决定下个月写什么、改什么、停什么。",{"title":23,"searchDepth":115,"depth":115,"links":453},[454,455,456,457,458,459,460,461],{"id":384,"depth":115,"text":384},{"id":393,"depth":115,"text":393},{"id":402,"depth":115,"text":402},{"id":411,"depth":115,"text":411},{"id":420,"depth":115,"text":421},{"id":427,"depth":115,"text":427},{"id":433,"depth":115,"text":433},{"id":442,"depth":115,"text":442},"内容运营","2025-12-15","我们的月度复盘只有四个指标：曝光、点击率、滚动到 75% 的比例、内容带来的注册或咨询。平均排名和字数早就不看了，看了也做不出动作。",{},"\u002Fblog\u002Fmonthly-content-review-metrics",{"title":376,"description":464},"blog\u002Fmonthly-content-review-metrics",[470,471,472],"内容评估","数据复盘","SEO指标","Xsg0ZzS3dnESC3_wapTngzpCkf-dlFUJSmXS2FpeNWs",1794088110049]