Go mod 好菜系列 - 0x19 consul 这锅服务发现不是配个地址本就完事
详细聊 consul 在服务发现和配置场景里的定位、注册发现到底解决什么问题、健康检查为什么关键,以及它适合哪些规模的服务系统。
单体时代很多配置都很朴素:地址写死、端口写死、上游服务写在配置文件里。可一旦服务多起来、实例会扩缩容、机器会漂移,你很快就会发现,“把地址写在那儿”这件事本身就是一笔债。consul 常常就是在这个阶段上桌的。
consul 最常被拿来干什么
- 服务注册与发现
- 健康检查
- 配置分发
- 简单的服务治理辅助
真正最常见的入口,还是前两项。项目一旦不再只有一台机器、一个实例,注册发现就很难靠手工维护撑住。
服务发现到底在解决什么
不是“我知不知道某个服务存在”,而是“我能不能在运行时拿到一组当前可用的服务实例”。这件事看起来像查电话簿,实际上关心的是动态变化:
- 实例新加了
- 实例挂了
- 实例不健康了
- 同一服务有多台可选
你会发现,这已经不是配置文件能优雅表达的事情了。
为什么健康检查很关键
注册发现如果只负责“登记名字”,那很快就会变成一个把坏实例也推荐出去的通讯录。consul 的价值之一,就是把“这个实例还活着吗”也纳入了系统。
服务可见,不等于服务可用。很多线上事故最后查下来,问题就出在“地址能连上,但业务已经半死不活”。
服务注册的参考代码
cfg := api.DefaultConfig()
cfg.Address = "127.0.0.1:8500"
client, err := api.NewClient(cfg)
if err != nil {
log.Fatal(err)
}
registration := &api.AgentServiceRegistration{
ID: "user-api-1",
Name: "user-api",
Port: 8080,
Address: "10.0.0.12",
Check: &api.AgentServiceCheck{
HTTP: "http://10.0.0.12:8080/healthz",
Interval: "10s",
Timeout: "2s",
},
}
if err := client.Agent().ServiceRegister(registration); err != nil {
log.Fatal(err)
}这段代码真正值得关注的是健康检查部分。注册只是把名字报上去,检查才决定这个实例是不是还能被安全地返回给调用方。
它适合什么样的项目
- 服务实例数量开始上来
- 部署频率较高
- 上游服务地址不再稳定
- 团队已经进入基本的微服务协作
这种场景里,consul 会比继续堆手写配置靠谱得多。
它不是用了就自动变高级
这里还是要踩个刹车。很多项目上了注册发现以后,仍然可能继续在客户端瞎缓存地址、继续忽略超时重试、继续把错误实例留在本地列表里。于是名义上用了服务发现,实际上调用体验并没有变好多少。
所以 consul 更像基础设施拼图的一块,而不是“用了就完成治理升级”的按钮。
配置中心这件事也常被一起提
不少团队会顺手把配置也放进 consul,但这块要看复杂度。简单配置当然能放,复杂配置管理、灰度、审核和回滚需求一多,就可能需要更专门的方案。
小结
consul 这锅菜主要解决的是“服务在动,调用方怎么跟上”:
- 它的核心价值是注册发现和健康检查
- 适合进入多实例、多服务阶段的系统
- 服务可见不等于服务可用,健康检查非常关键
- 它是治理拼图的一块,不是完整治理方案本身