599_Consul服务发现
一句话概述:HashiCorp Consul 是分布式服务发现和配置管理工具,让微服务之间能自动找到彼此(服务发现),同时提供健康检查、KV 存储、服务网格(Service Mesh)和多数据中心支持,是微服务架构的"电话簿+健康管家"。
核心知识点表
| 概念 | 白话解释 |
|---|
| Service Discovery | 服务发现,服务自动注册和查找(不用硬编码 IP) |
| Health Check | 健康检查,定期检测服务是否正常运行 |
| KV Store | 键值存储,集中管理配置(类似 etcd) |
| Service Mesh | 服务网格,通过 Sidecar 代理管理服务间通信 |
| Agent | 代理,每个节点上运行的 Consul 进程(Server 或 Client) |
| Catalog | 服务目录,所有注册服务的中心数据库 |
| Connect | Consul 的服务网格功能,提供 mTLS 加密和访问控制 |
安装配置
安装 Consul
# macOS
brew install consul # Homebrew 安装
# Ubuntu/Debian
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install consul
# Docker
docker run -d --name consul \
-p 8500:8500 \ # Web UI 和 HTTP API
-p 8600:8600/udp \ # DNS 接口
hashicorp/consul:latest agent \
-dev \ # 开发模式
-client=0.0.0.0 # 允许外部访问
# 验证安装
consul version # 查看版本(当前 v1.22.x)
# 访问 http://localhost:8500 查看 Web UI
生产集群部署
# server.hcl — Server 节点配置
datacenter = "dc1" # 数据中心名
data_dir = "/opt/consul/data" # 数据目录
server = true # Server 模式
bootstrap_expect = 3 # 期望 3 个 Server 节点
bind_addr = "{{ GetPrivateInterfaces | attr \"address\" }}" # 绑定私网 IP
ui_config {
enabled = true # 启用 Web UI
}
client_addr = "0.0.0.0" # 允许外部访问 API
connect {
enabled = true # 启用服务网格
}
# ACL 配置(生产必须)
acl {
enabled = true # 启用 ACL
default_policy = "deny" # 默认拒绝
enable_token_persistence = true # Token 持久化
}
# 启动 Server 集群
# 节点1
consul agent -config-file=server.hcl
# 节点2、3 加入集群
consul agent -config-file=server.hcl -retry-join=SERVER1_IP
# Client 节点(运行在应用服务器上)
consul agent -data-dir=/opt/consul/data \
-retry-join=SERVER1_IP \ # 加入集群
-bind=LOCAL_IP # 本机 IP
基本使用
服务注册
// 方法1:配置文件注册
// /etc/consul.d/web-service.json
{
"service": {
"name": "web", // 服务名
"port": 8080, // 服务端口
"tags": ["v1", "production"], // 标签
"check": { // 健康检查
"http": "http://localhost:8080/health", // 检查 URL
"interval": "10s", // 每 10 秒检查一次
"timeout": "3s" // 超时 3 秒
}
}
}
# 重新加载配置
consul reload # 重新加载服务定义
# 方法2:HTTP API 注册
curl -X PUT http://localhost:8500/v1/agent/service/register \
-d '{
"Name": "api-service",
"Port": 3000,
"Tags": ["v2"],
"Check": {
"HTTP": "http://localhost:3000/health",
"Interval": "10s"
}
}'
# 方法3:CLI 注册
consul services register web-service.json # 注册服务
consul services deregister web-service.json # 注销服务
服务发现
# === DNS 方式(推荐) ===
# Consul 内置 DNS 服务器(端口 8600)
dig @localhost -p 8600 web.service.consul # 查询 web 服务的 IP
# 返回所有健康的 web 服务实例 IP
dig @localhost -p 8600 web.service.consul SRV # 查询包含端口的 SRV 记录
# 带标签查询
dig @localhost -p 8600 v1.web.service.consul # 只查 v1 标签的实例
# === HTTP API 方式 ===
curl http://localhost:8500/v1/catalog/service/web # 查询服务
curl http://localhost:8500/v1/health/service/web?passing # 只返回健康的
# === CLI 方式 ===
consul catalog services # 列出所有服务
consul catalog nodes # 列出所有节点
KV 存储
# 写入配置
consul kv put config/db/host "db.example.com" # 写入键值
consul kv put config/db/port "5432" # 写入端口
consul kv put config/app/settings @settings.json # 从文件写入
# 读取配置
consul kv get config/db/host # 读取值
consul kv get -detailed config/db/host # 读取详细信息(含版本)
# 列出键
consul kv get -recurse config/ # 列出 config/ 下所有键值
# 删除键
consul kv delete config/db/host # 删除单个键
consul kv delete -recurse config/old/ # 递归删除
# 导出/导入
consul kv export config/ > backup.json # 导出
consul kv import @backup.json # 导入
高级用法
服务网格(Connect)
# 使用 Envoy Sidecar 代理实现 mTLS 和访问控制
# web-service.hcl — 带 Connect 的服务定义
service {
name = "web"
port = 8080
connect {
sidecar_service { # Envoy Sidecar
proxy {
upstreams { # 上游服务(要调用的服务)
destination_name = "api" # 目标服务名
local_bind_port = 9191 # 本地绑定端口
}
}
}
}
}
# web 服务通过 localhost:9191 访问 api 服务
# Consul 自动处理 mTLS 加密和服务发现
# 启动 Sidecar 代理
consul connect envoy -sidecar-for web # 启动 web 的 Sidecar
# 配置访问意图(Intentions)
# 允许 web 访问 api
consul intention create web api # 允许
# 禁止 web 访问 database
consul intention create -deny web database # 拒绝
Consul Template(动态配置)
# 安装 consul-template
wget https://releases.hashicorp.com/consul-template/0.41.0/consul-template_0.41.0_linux_amd64.zip
unzip consul-template_*.zip
sudo mv consul-template /usr/local/bin/
# nginx.conf.ctmpl — Consul Template 模板
upstream backend {
{{ range service "api" }} # 遍历所有 api 服务实例
server {{ .Address }}:{{ .Port }}; # 动态生成 upstream
{{ end }}
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
# 运行 consul-template
consul-template \
-template "nginx.conf.ctmpl:nginx.conf:nginx -s reload"
# 监听 Consul 中 api 服务的变化
# 自动重新生成 nginx.conf 并 reload Nginx
多数据中心
# Consul 原生支持多数据中心
# 每个数据中心有自己的 Server 集群
# 通过 WAN Gossip 协议互相发现
# 查询远程数据中心的服务
dig @localhost -p 8600 web.service.dc2.consul # 查询 dc2 的 web 服务
curl http://localhost:8500/v1/catalog/service/web?dc=dc2 # API 方式
常见报错
| 报错信息 | 原因 | 解决方案 |
|---|
No cluster leader | 没有 Leader 节点 | 检查 Server 节点数(至少 3 个) |
ACL not found | ACL Token 无效 | 创建或更新 Token |
health check failing | 健康检查失败 | 检查服务端口和检查 URL |
rpc error: agent not found | Agent 未运行 | 启动 Consul Agent |
port already in use | 端口冲突 | 修改端口或停止占用进程 |
速查表
# === 服务操作 ===
consul services register FILE # 注册服务
consul services deregister FILE # 注销服务
consul catalog services # 列出服务
consul catalog nodes # 列出节点
# === KV 操作 ===
consul kv put KEY VALUE # 写入
consul kv get KEY # 读取
consul kv delete KEY # 删除
consul kv export PREFIX # 导出
# === 集群管理 ===
consul members # 查看集群成员
consul operator raft list-peers # 查看 Raft 节点
consul info # 查看信息
consul reload # 重新加载配置
# === 关键端口 ===
# 8500 → HTTP API 和 Web UI
# 8600 → DNS 接口
# 8301 → LAN Gossip(节点发现)
# 8302 → WAN Gossip(跨数据中心)
# 8300 → RPC(Server 间通信)
# === 健康检查类型 ===
# HTTP → 检查 HTTP 端点
# TCP → 检查 TCP 端口
# Script → 运行脚本检查
# TTL → 服务主动上报
# gRPC → 检查 gRPC 端点
同类对比
| 特性 | Consul | etcd | ZooKeeper | Nacos |
|---|
| 服务发现 | 内置 | 需扩展 | 需扩展 | 内置 |
| 健康检查 | 内置 | 无 | 有限 | 内置 |
| KV 存储 | 内置 | 核心 | 核心 | 内置 |
| 服务网格 | Connect | 无 | 无 | 无 |
| 多数据中心 | 原生 | 有限 | 有限 | 有限 |
| DNS 接口 | 内置 | 需 CoreDNS | 无 | 无 |
| 学习曲线 | 中等 | 低 | 高 | 低 |
选型建议:需要完整服务发现+服务网格选 Consul(功能最全);只需分布式 KV 存储选 etcd(K8s 默认使用);Java/Spring Cloud 生态选 Nacos(阿里开源)。