一个永远只指向可达实例的分布式注册表

Consul 维护一份存活的健康服务清单

服务注册表的价值完全取决于它有多诚实。Consul 把注册的实例收进 catalog,并给它们挂上健康检查,于是「某个服务的健康实例在哪」这个问题的答案会随现实变化。注册本身很简单;检查才是全部的产品价值,因为一份列出死实例的注册表比静态清单更糟——它会主动把流量送进坑里。 这个答案的新鲜程度,取决于两个第一周之后没人再看的选择:检查多久跑一次,以及它到底测的是什么。每 30 秒跑一次的检查会瞎 30 秒;只证明进程存在的检查则永远瞎着。 注册,以及两个层级的检查 实例通过配置文件或注册 API 登记名字、地址、端口以及一条或多条检查。检查默认以 critical 状态起步,这是刻意的:在健康至少被验证过一次之前,服务无法进入可用池——想要初始就是 passing,必须显式写出来。检查的状态由它自己判定:脚本检查按退出码决定(0 为通过、非 0 为 critical),HTTP 检查按响应码决定,输出超过 4KB 会被截断,脚本检查默认 30 秒超时。也就是说,「检查通过」这几个字的含义完全取决于你写的那条命令。 同一台节点上有两个层级的检查。serfHealth 这样的节点级检查服务名为空,描述的是这台机器;service:web-1 这样的服务级检查绑定在某一条注册上。它们各自独立失败,但只取健康的过滤器要求节点上所有检查都通过,所以节点级检查变 critical 会一次带走这台机器上的所有服务,而服务级检查变 critical 只移除一个实例。 调用方实际拿到什么 catalog 会回答两个不同的问题。不加过滤时,/v1/health/service/web 返回全部注册以及每条检查的状态;加上 passing=true 时,只返回所有检查都通过的实例。DNS 与 SRV 永远按第二种方式回答,所以解析器不会拿到一个不能用的名字,而这个通过集合就是负载均衡池。 catalog 同时也是最终一致的,机制叫反熵。注册是即时的——agent 会通知 leader——但修复是周期性的:每个 agent 按一个间隔把自己的本地状态与 catalog 对齐,128 个节点以内的集群是 1 分钟,随集群规模增长而变长,并且每个 agent 的起始时间都会错开,以免所有人同时同步。同步失败只会被记进日志、等下一个周期重试,所以一条错误的 catalog 记录可以安静地存活长达一个间隔。读路径也有自己的取舍:默认情况下 agent 会把 catalog 读请求转发给 leader,并用一个假定领导地位短期稳定的 leader lease,因此很快但偶尔可能返回陈旧结果;consistent 模式要求 leader 先向多数派确认自己仍是 leader,stale 模式则允许任何 server 不做检查就回答。这三档没有对错,只有你愿意为一个多新的答案付出多少延迟。 ...

四月 6, 2028 · 1 分钟 · XB Field Notes
以观察、判断和行动三个面板呈现 sitemap 条目验证。

Sitemap 帮助爬虫发现页面

Sitemap 为爬虫提供一份明确的候选网址清单,适合帮助发现新内容或普通导航中较深的文档。这份列表不会绕过登录、授予抓取权限、保证搜索收录,也不能承诺某天一定重新访问。应把它视为计划公开文档的发布清单,并让清单与规范网址及实际发布状态保持一致。文件成功上传,只能说明某一步交付发生了,不能替代后续抓取和收录证据。 从发布清单生成 使用与公开页面相同的权威内容筛选规则,排除草稿、私有文档和多余的跟踪参数变体。源码目录里存在一个文件,不代表它已经对应公开 URL;反过来,分页、翻译文档或生成路由,也未必与源文件逐一对应。因此需要查看生成器实际输出,而不是仅凭目录列表猜测发布范围。内容筛选与 sitemap 生成相互独立维护,容易出现遗漏或提前暴露未发布入口。 XML sitemap 使用声明的命名空间,以及包含网址条目的 urlset,每个 loc 提供完整网址。XML 转义与 URL 编码解决不同问题:分隔查询参数的与号,需要在 XML 文本里转义,而网址本身的字符也必须符合相应 URI 表示方式。生成后应重新解析文件,确认经过两层处理,仍然得到原本希望发布的网址,不能因为 XML 看起来能打开就省略这一检查。 还要遵守格式的范围与大小条件。通常应列出相应主机及允许位置范围内的网址,受支持的跨站提交安排有额外规则。每份 sitemap 最多五万个网址,未压缩内容不得超过 52,428,800 字节。gzip 可以减少传输量,却不能取消解压后的上限。更大的清单应拆分并使用适当索引,不能为了让文件通过检查而悄悄截断后面的页面。 坏掉的样子 XML 合法的文件,仍可能列出跳转、缺失页面或不应进入索引的内容。应同时验证目标与语法,并让目标上的 canonical 声明符合预期清单。某个地址返回二百,却只有登录界面或通用错误页,不能证明列出的文档真正可用。Sitemap 自身成功交付,与其描述的页面是否有用,需要分别检查,不能在一个状态码上完成所有判断。 修改时间也可能失真。提供 lastmod 时,应依据页面有意义的变化,而不是每次构建都刷新所有条目的时间。Google 明确说明,它会使用持续准确的 lastmod,并忽略 priority 和 changefreq。这些字段不是调度接口,把所有页面都标成最高优先级,也不能命令爬虫增加访问。没有可信历史依据时,省略可选字段比编造精确时间更诚实。 ...

六月 30, 2027 · 2 分钟 · XB Field Notes
以观察、判断和行动三个面板对比爬虫规则与实际 HTTP 访问。

robots.txt 引导抓取,但不授予或禁止访问

robots.txt 向实现 Robots Exclusion Protocol 的自动客户端传达抓取规则,可以减少对昂贵或无用路径的遍历,但服务器不会因此自动按照文件内容拦截请求。RFC 9309 明确区分这些规则与访问授权。应把它当作面向合作爬虫的公开接口,真正能否读取受保护资源,仍由认证和授权机制决定。配置中写了禁止抓取,不等于服务器已经建立了权限边界。 对准目标爬虫与实际路径 标准文件位于相应方案和 authority 的 /robots.txt,放在应用子目录下的同名文件,不会自动成为整个源站的策略。User-agent 分组标识规则面向的爬虫产品,通配分组按协议为其他代理提供适用规则。路径规则针对请求目标匹配,大小写不同可能产生不同结果。路由变化时应重新检查具体 URL,不能只看规则文字仍然像原来的样子。 文件应以 UTF-8 纯文本形式提供,并明确实际响应。宽泛的静态站回退规则,可能在 robots 路径返回二百和首页内容;这只证明 HTTP 已经交付,不能证明爬虫取得了预期策略。复杂的 Allow、Disallow 组合、转义和通配模式,需要对照协议及真实爬虫实现验证。一个简单解析器案例不能替整个规则集合证明所有边界行为正确。 坏掉的样子 在 robots.txt 中列出私有路径,并不会隐藏路径;公开的规则文件反而可能告诉别人它在哪里。客户端可以完全不读策略就直接请求,合作爬虫自己作出的不抓取决定,也不会转化为源站上的访问规则。确实需要限制的内容,应在请求授权的位置执行限制;Disallow 行不能替代账号权限或其他实际访问检查。公开规则和私有资源的保护条件必须分开维护。 抓取与收录也是不同问题。Google 文档说明,被禁止抓取的 URL 仍可能因为其他来源的链接出现在搜索结果里。如果爬虫无法读取页面,也可能看不到页面上希望它执行的 noindex 指令。公开内容需要按目标选择合适的收录控制,私有内容则要使用真实访问限制。不能认为阻止内容下载,就会自动移除所有已存在的搜索记录或外部引用。 策略获取失败同样有不同语义。RFC 9309 允许爬虫在文件不可用时访问资源,例如收到四开头的 HTTP 响应;如果服务器或网络错误导致文件无法到达,例如五开头的响应,爬虫起初必须假定完全禁止。规范还定义了长期失败与缓存副本的处理。部署坏了 robots 文件,可能改变抓取行为,不应只把它当成少了一份装饰性文本。 ...

十月 2, 2026 · 2 分钟 · XB Field Notes