← 学习路线

从输入网址到看到页面

在地址栏按下回车之后,页面出现之前,请求走过了哪几站?卡在某一站时,你会看到什么?

课型:流程·约 25 分钟·6 个术语

先看出事的那一刻

2026 年 7 月 27 日,自动驾驶知识站准备上线。前端和后端都部署在一个叫 Railway 的平台上,平台给的默认地址打开一切正常。只剩最后一步:让 e2e.felixwithai.com 也能打开它。

DNS 记录加好了,平台很快显示记录已生效,证书却一直停在"验证所有权"。这期间访问域名,浏览器直接拒绝连接:平台出示的是一张写着 *.up.railway.app 的通用证书,和域名对不上。一个多小时后证书终于签了下来,页面又换成了平台自己的一句 Application not found。平台后台显示域名已激活、证书有效;删掉域名重建,只换来一个新的 CNAME 目标。

这节课要回答的是:在地址栏按下回车之后,页面出现之前,请求走过了哪几站?卡在某一站时,你会看到什么?

装备几个词

为什么要懂

AI 替你做了

托管平台把域名、证书、全球分发都做成了几个按钮,AI 也能替你一步步点完。大多数时候,一次就通。

留给你的

没通的那一次。你要能分辨卡在了哪一站:DNS、证书、平台还是代理,才知道该等、该改,还是该换条路。

不懂的代价

上线当天对着一个打不开的域名反复删除、重建、等待,每一轮都要几十分钟,却一直在错误的那一站打转。

一次访问,五站路

在地址栏按下回车,到页面出现,请求大致要走五站:

  1. 问路(DNS):浏览器拿着域名去问"它在哪",得到一个地址。
  2. 验明身份(HTTPS):连上那个地址,对方出示证书,证明自己确实是这个域名的主人,双方约好加密方式。
  3. 就近取货(CDN):网站放在 CDN 上时,接待你的是离你最近的边缘节点,静态文件直接从这里返回。
  4. 前台转交(反向代理):需要后端处理的请求,由前台按规则转给后面真正干活的服务。
  5. 后厨出菜(源站):后端处理请求,结果沿原路送回,浏览器画出页面。

不是每个网站都有五站:纯静态的网站到第三站就结束了。排查时最有用的,是记住卡在每一站时,你会看到什么:

卡在哪你会看到先查什么
DNS"找不到服务器"记录加了没有、指向哪里、旧缓存过期没有
证书"你的连接不是私密连接",或者证书上的名字对不上证书签给了谁、签下来没有
平台没认出这个域名平台自己的错误页,比如 Application not found平台后台有没有登记并激活这个域名
代理规则拿到了不该拿到的东西,比如该给数据的地方给了一张网页转发规则覆盖了哪些路径
源站502、503、504后端进程是否在运行,日志里有什么

对照这张表看 7 月 27 日:证书签下来之前,卡在证书那一站,浏览器拒绝连接;证书签下来之后,DNS 和证书都通了,请求已经到了平台门口,平台却认不出这个域名。这时后台显示一切正常,出问题的是平台自己的边缘路由。谁回的话,请求就至少走到了谁那里:看到平台的错误页,就别再回头改 DNS 了。

深潜为什么不能让 Cloudflare 直接代理过去+

Railway 按请求里的 Host,也就是访客要找的域名,决定把请求交给哪个服务。经过 Cloudflare 代理时,Host 仍然是 e2e.felixwithai.com,正是 Railway 认不出的那个名字。要把 Host 改写成平台认得的默认域名,Cloudflare 免费版没有这个功能。

7 月 28 日晚上又试过一次:把域名直接指回 Railway,并打开 Cloudflare 代理。页面上出现的是另一句错误,The train has not arrived at the station.,几分钟后又改了回去。

绕过去的那条路

最后的办法,是换一条每一站都确定没坏的路:

  1. 域名的 CNAME 记录指向 Cloudflare Pages,经过 Cloudflare 代理,证书由 Cloudflare 出示;
  2. 前端的静态页面放在 Pages 上,由边缘节点直接返回;
  3. /api/ 开头的请求,由一段 Worker 脚本转给 Railway 的默认地址。那个地址一直是好的,而且脚本转发时,Host 会自动换成它。

换了这条路,域名很快就通了。代价是链路上多了一站,而且这一站归你自己负责:规则漏了什么,就会漏掉什么。下面的找茬,就是这一站。

深潜用命令看清每一站+
dig +short 你的域名                     # 第一站:解析到了哪里
curl -sv https://你的域名 2>&1 | grep -E "subject:|issuer:"   # 第二站:证书签给了谁、由谁签发
curl -sI https://你的域名               # 是谁在回答、状态码是多少

经过 Cloudflare 代理的域名,dig 只会看到 Cloudflare 的地址,证书的签发方也是 Cloudflare 那边的机构。这不是出错,而是说明第一、二站都由 Cloudflare 接管了。

找茬

下面是上线后那一站的真实代码,以及一次部署命令(节选并略作简化),都出自 AI 之手。站长的要求是:前端和后端共用一个域名,导师的回答要能流式输出,后端出了问题要看得出来。

这段 JS / Shell 里埋了 5 处问题。点击你觉得有问题的行,至少找出 3 处再揭晓。

查看代码与答案(5 处问题)
 1  // web/public/_worker.js(Cloudflare Pages 上的转发脚本,节选)
 2  const ORIGIN = "https://e2e-academy-production.up.railway.app";
 3  
 4  export default {
 5    async fetch(request, env) {
 6      const url = new URL(request.url);
 7      // new Request(target, request) 会把 Host 换成目标主机,
 8      // 这正是 Railway 边缘认得的那个域名。
 9      // Workers 的 fetch 默认流式透传,SSE(/api/tutor)不受影响。
10      if (url.pathname.startsWith("/api/")) {
11        const target = new URL(url.pathname + url.search, ORIGIN);
12        return fetch(new Request(target, request));
13      }
14      // ……其余请求交给 Pages 上的静态页面(略)
15    },
16  };
17  
18  # 7 月 28 日晚:给转发规则补上 /healthz 并上线后,又重新构建、部署了一次前端
19  npx vite build && cp -r dist/* $D/ && npx wrangler pages deploy $D
  • 第 2 行 · 中危 · 后端的默认地址,谁都能直接访问:转发脚本只是多了一个入口,并没有把后端藏起来。Railway 的默认地址一直对所有人公开,绕过这个脚本就能直接调用后端;后端还顺手托管了一份完整的前端,同一个网站出现了两个公开入口。 该问的话:绕过转发脚本、直接访问后端的默认地址,会发生什么?
  • 第 9 行 · 中危 · 没验证过的结论,写成了注释:导师的回答要经过 Cloudflare 一段一段流回来。搬到 Pages 之前,DNS 特意设成不经过 Cloudflare 代理,理由正是担心它缓冲流式输出;搬过去之后,没有人经过这个域名实际测过一次导师。注释写得很笃定,其实只是一个猜测。 该问的话:经过这个域名问一次导师,回答是一段一段出来的,还是最后一次性出来的?
  • 第 10 行 · 中危 · 只转发 /api/ 开头的请求:/healthz、少了斜杠的 /api,都不符合这条规则,会落到静态页面那边,被当成一个页面返回 200。第 5 课的事故就从这里来。 该问的话:哪些路径会被转给后端?/healthz 呢?
  • 第 12 行 · 中危 · 后端出错或超时,没有任何兜底:没有超时,也没有错误处理:后端很慢时,请求一直挂着;连接失败时,异常没人接住,访客多半会看到 Cloudflare 的通用错误页,而不是一段前端能读懂的 JSON。 该问的话:后端挂了或者很慢的时候,这里会返回什么?前端能正确提示吗?
  • 第 19 行 · 高危 · 旧脚本随构建产物回来,覆盖了刚上线的修复:补上 /healthz 的新脚本只改在了部署目录里,没有提交进仓库。重新构建时,仓库里的旧脚本随着 dist/* 被拷回部署目录,一分钟前的修复就此消失。此后两个月,线上跑的一直是旧脚本。 该问的话:刚才的修复提交进仓库了吗?下一次构建会不会把它覆盖掉?

快测

1. 你给域名加好了 DNS 记录,打开网站,看到的是托管平台自己的错误页 Application not found。问题最可能卡在哪?

查看选项与答案
  • A. 后端崩溃了,平台替它显示了错误页——错误页多半是我的程序出的事。可后端崩溃通常表现为 502、503 这类状态码,而且请求得先被交到你的服务,才会走到这一步。
  • B. 平台还没有把这个域名对应到你部署的服务(正确)——能看到平台的错误页,说明 DNS 和连接都通了,请求已经到了平台门口,只是平台不知道该交给谁。去平台后台看看有没有登记并激活这个域名。
  • C. DNS 记录还没生效,还得再等一阵——打不开就怪 DNS,是最常见的反应。可 DNS 没生效的话,请求根本到不了平台,你也就看不到平台的错误页。谁回的话,请求就至少走到了谁那里。

看错误页是谁给的:谁回的话,请求就至少走到了谁那里。

2. 网站经过 Cloudflare 代理之后,访客在浏览器里看到的 HTTPS 证书,是谁出示的?

查看选项与答案
  • A. 后面的托管平台,Cloudflare 只是把流量原样转过去——代理只是一根透明的管子,证书还是平台的。可代理模式下,访客连接的是 Cloudflare 的边缘节点,出示证书的是它;平台的证书只用在 Cloudflare 到平台的那一段。
  • B. Cloudflare 的边缘节点,而不是后面的平台(正确)——访客到 Cloudflare、Cloudflare 到源站,是两段各自加密的连接,每一段有自己的证书。访客看到的是第一段的。
  • C. 访客这一段没有证书,只有转发给平台那段才用 HTTPS——代理会把访客这一段变成明文。可两段连接都要加密,只是出示证书的人不同。

中间多一层代理,就多一段连接、多一张证书。

3. 你改完 DNS 记录,自己这边已经能打开新网站,同事那边还是旧的。最可能的原因是?

查看选项与答案
  • A. 新网站只对部署它的账号开放,同事没有访问权限——新网站带着访问限制。可绑定域名之后,网站对所有人都一样;同事看到的是旧网站,而不是被拒绝访问,说明同事的请求还被送去了旧地址。
  • B. 同事那边的 DNS 查询结果还在缓存里(正确)——各级缓存会按记录的 TTL 保留旧结果,缓存过期之前,同事仍会被指向旧地址。过一阵就会更新。
  • C. 证书还没签下来,同事那边被拦住了——证书没签好,同事才被拦住。可你自己能正常打开,说明证书没问题;证书的问题会让所有人都打不开、看到证书警告,而不是有人新、有人旧。

DNS 改动是逐步生效的,新旧地址会并存一阵。

判断时刻

上线当天,自定义域名卡住了:DNS 已生效,证书也签下来了,访问却一直是平台的 Application not found,平台后台显示一切正常。AI 给了三个方案。

你会怎么做?

三个选项各自的代价
  • A. 删除域名,重新添加,再等一轮——考察等待的成本:这是平台文档里的标准动作,值得试一次。但这一次试了三轮,每轮只换来一个新的 CNAME 目标,一轮就是几十分钟,上线时间一直往后拖。
  • B. 提交工单,等平台修好边缘路由——考察依赖他人:最省事,也最“正确”,架构不用动。代价是时间不在你手里,工单可能要几天,上线计划只能停着。
  • C. 换一条路:前端放到 Cloudflare Pages,用一段转发脚本把 /api 请求交给平台的默认地址——考察绕路的代价:每一站都换成了确定没坏的环节,很快就能通。代价是多了一个转发层,它的规则要写对、要验证,后端的默认地址也仍然对外公开。这一次最后选的就是这条路。

先判断卡在哪一站,再决定是等、是催,还是绕。卡在别人的平台里时,绕路往往最快,但绕出来的那段路,从此由你自己负责。

带走

下次让 AI 做这件事时,问它

  1. 从访客输入网址到拿到页面,这个网站的请求要经过哪几站?每一站由哪个平台负责?
  2. 域名的 DNS 记录指向哪里?经不经过代理?证书由谁签发、会不会自动续期?
  3. 如果中间有转发脚本:它转发哪些路径?后端出错或超时时返回什么?后端的默认地址是不是也对外公开?
  4. 改过部署目录里的文件之后,改动提交进仓库了吗?下一次构建会不会把它覆盖?

自己验证

  • dig +short 你的域名:看域名解析到了哪里(经过 Cloudflare 代理时,只会看到 Cloudflare 的地址)。
  • curl -sI https://你的域名:看是谁在回答、状态码是多少。
  • curl -s https://你的域名/api/某个接口 | head -c 200:看返回的是不是后端给的数据,而不只看状态码。

打不开的时候,先问:请求走到了哪一站?谁回的话,它就至少到了谁那里。