5月30日 22:56

Consul 服务发现是如何完成注册、健康检查和查询的?

Consul 的服务发现可以拆成三步:服务把地址、端口和健康检查注册到本机 Consul Agent;Agent 定期执行检查,并把状态同步到 Consul server;调用方通过 DNS 或 HTTP API 查询健康实例,再由客户端、网关或负载均衡器决定访问哪一个。关键点是服务通常不是直接注册到远端 server,而是注册到同机或同网段的 client agent。这样服务上下线、健康检查和网络抖动都先在本地处理,server 负责维护一致的服务目录。

服务定义可以放在 /etc/consul.d/web.json

json
{ "service": { "id": "web-10-0-1-12", "name": "web", "address": "10.0.1.12", "port": 8080, "tags": ["v1", "blue"], "checks": [{ "id": "web-http", "http": "http://10.0.1.12:8080/health", "interval": "10s", "timeout": "2s", "deregister_critical_service_after": "1m" }] } }

重新加载后即可注册和查询:

bash
consul reload consul catalog services curl 'http://127.0.0.1:8500/v1/health/service/web?passing=true' dig @127.0.0.1 -p 8600 web.service.consul

HTTP API 返回信息完整,适合网关、控制面或自定义客户端;DNS 接口语言无关,适合旧系统或不想引 SDK 的应用。取舍也很清楚:HTTP 能拿到 tags、checks、metadata 和过滤参数,但要解析 JSON;DNS 接入成本低,但复杂灰度和权重逻辑通常要交给网关。生产查询建议加 passing=true,否则调用方可能拿到已经失败但还留在目录里的实例。

追问

服务应该注册到 Consul server 还是 client agent?

推荐注册到本机或本地网络里的 client agent,而不是让每个应用直接写 server。client agent 负责本机服务注册、健康检查和请求转发,server 负责维护目录。这样 server 故障、Leader 切换或网络抖动时,应用侧改动更少。踩坑点是容器环境里 address 填成 127.0.0.1,别的服务发现后根本访问不到。

DNS 查询和 HTTP API 查询怎么选?

DNS 查询最简单,很多老应用只要改解析配置就能接入 web.service.consul。HTTP API 信息更丰富,可以按 tag、健康状态和数据中心过滤,也能拿到服务元数据。边界是 DNS 只返回地址类结果,不适合承载复杂版本和灰度逻辑。常见做法是基础服务用 DNS,网关或服务框架用 HTTP API 做精细路由。

健康检查失败后服务会立刻消失吗?

不会,Consul 会先把 check 标记为 warning 或 critical,服务目录中仍可能存在。使用 /v1/health/service/web?passing=true 才会只拿到健康实例。deregister_critical_service_after 可以让长期 critical 的服务自动注销,但时间不要设太短。这个取舍是保留诊断信息,同时让调用方有能力过滤不可用实例。

Consul 是否负责客户端负载均衡?

Consul 主要负责发现和健康状态,不直接替应用完成每次请求的负载均衡。DNS 返回多个 A 记录时可能轮询,但行为受缓存、TTL 和语言运行时影响。HTTP API 返回实例列表后,客户端或网关仍要自己做轮询、随机、权重、就近访问和重试。不要把 Consul 当成 Nginx 或 Envoy,它更像服务目录和健康数据源。

标签:Consul