Consul注册必须显式配置健康检查,否则服务状态为critical;注册时需在api.AgentServiceRegistration中设置非空Checks字段,推荐HTTP探针指向/health端点,Timeout设2s、Interval设5s,并在查询时用Health().Service()配合PassingOnly:true确保只获取健康实例。

Consul注册必须显式配置健康检查,否则服务状态为critical
很多团队在Gin服务启动后去Consul UI里看到服务状态是critical,点进去发现Health Check显示Missing——这不是Consul挂了,而是注册时漏传Check字段。Consul不会自动帮你加HTTP探针,你得自己指定路径、超时和间隔。
- 注册代码里必须构造
api.AgentServiceRegistration,其中Checks字段不能为空;推荐用api.AgentServiceCheck.HTTP指向/health端点(Gin需提前暴露该路由) -
Timeout建议设为2s,Interval设为5s,太短容易误判,太长故障发现延迟高 - 别依赖
consul agent -dev的默认行为——它只开单节点且不校验Check,生产集群必须显式配置
Gin服务发现客户端查服务时,PassingOnly: true不能省
用api.Health().Service查服务列表时,默认返回所有状态的服务实例(包括critical和warning),如果没加PassingOnly: true,你的负载均衡器可能把请求打到已宕机但尚未被Consul剔除的实例上。
- 正确调用方式:
api.Health().Service("user-service", "", true, &api.QueryOptions{AllowStale: false}),第三个参数就是PassingOnly -
AllowStale: false确保读取的是强一致性数据,避免因Consul follower节点延迟导致拿到过期列表 - 别直接用
net.LookupHost("user-service.service.consul")——Docker容器内默认没有Consul DNS解析支持,除非你部署了consul-template或dnsmasq
配置热更新要用Consul KV + Gin中间件兜底
Consul KV本身不推配置变更,Gin应用要实现配置热更新,得自己监听KV变化并触发重载。但watch机制不可靠:网络抖动、Consul重启都可能导致事件丢失,所以必须加本地缓存+定时拉取兜底。
- 初始化时先
api.KV().Get一次获取全量配置,再启动api.KV().Watch监听config/user-service/前缀 - Watch回调里不要直接修改全局变量——用
sync.RWMutex保护配置结构体,避免Gin handler并发读写panic - 必须设置
time.AfterFunc(30*time.Second, reloadFromKV)作为保底:即使watch断开,30秒内也会强制刷新一次 - 配置项如
database.url应通过viper.WatchRemoteConfigOnChannel桥接,而不是手写JSON解析逻辑
Docker部署时Consul地址不能写localhost
本地开发用http://localhost:8500注册没问题,但Docker容器里localhost指向容器自身,不是宿主机。K8s里更复杂,Service DNS名(如consul.default.svc.cluster.local)和Headless Service的Endpoint都得对齐。
- 容器化部署必须用可路由的Consul地址:Docker Compose用
consul:8500(依赖network别名),K8s用consul-headless.default.svc.cluster.local:8500 - 环境变量注入Consul地址比硬编码更安全:
CONSUL_ADDR=consul:8500,Gin启动时读os.Getenv("CONSUL_ADDR") - 启动Gin前加健康检查脚本:
until curl -f http://consul:8500/v1/status/leader; do sleep 2; done,避免Consul还没就绪Gin就注册失败


















