以下是 Consul、Etcd、Zookeeper、Nacos 在服务注册与发现中的实现示例,结合其核心特性、代码演示及对比分析。
一、Consul
特点:
- 支持服务发现、健康检查、KV 存储、多数据中心。
- 基于 HTTP/DNS 接口,提供长轮询和 Watch 机制。
服务注册:
# 通过 HTTP API 注册服务
curl -X PUT \
http://localhost:8500/v1/agent/service/register \
-H 'Content-Type: application/json' \
-d '{
"ID": "user-service-1",
"Name": "user-service",
"Address": "10.0.0.1",
"Port": 8080,
"Check": {
"HTTP": "http://10.0.0.1:8080/health",
"Interval": "10s"
}
}'
服务发现:
# 查询健康服务列表
curl http://localhost:8500/v1/health/service/user-service?passing
Go 客户端示例:
package main
import (
"fmt"
"github.com/hashicorp/consul/api"
)
func main() {
// 连接 Consul
config := api.DefaultConfig()
config.Address = "localhost:8500"
client, _ := api.NewClient(config)
// 注册服务
registration := &api.AgentServiceRegistration{
ID: "user-service-1",
Name: "user-service",
Port: 8080,
Check: &api.AgentServiceCheck{
HTTP: "http://localhost:8080/health",
Interval: "10s",
},
}
client.Agent().ServiceRegister(registration)
// 发现服务
services, _, _ := client.Health().Service("user-service", "", true, nil)
for _, service := range services {
fmt.Printf("Service: %s:%d\n", service.Service.Address, service.Service.Port)
}
}
二、Etcd
特点:
- 分布式键值存储,强一致性,基于 gRPC 协议。
- 常用于 Kubernetes 底层服务发现。
服务注册(使用 etcd3 API):
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main() {
// 连接 Etcd
cli, _ := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"},
DialTimeout: 5 * time.Second,
})
defer cli.Close()
// 注册服务(租约机制)
lease, _ := cli.Grant(context.TODO(), 10) // 10秒租约
_, _ = cli.Put(context.TODO(), "/services/user-service/10.0.0.1:8080", "", clientv3.WithLease(lease.ID))
// 自动续约保持服务在线
keepAlive, _ := cli.KeepAlive(context.TODO(), lease.ID)
go func() {
for range keepAlive {
// 续约成功
}
}()
// 服务发现
resp, _ := cli.Get(context.TODO(), "/services/user-service/", clientv3.WithPrefix())
for _, kv := range resp.Kvs {
fmt.Printf("Service: %s\n", kv.Key)
}
}
三、Zookeeper
特点:
- 基于 ZAB 协议的分布式协调服务,提供临时节点(Ephemeral Nodes)和 Watcher 机制。
服务注册(使用 Apache Curator 框架):
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
public class ZkServiceRegistry {
public static void main(String[] args) throws Exception {
// 连接 Zookeeper
CuratorFramework client = CuratorFrameworkFactory.newClient(
"localhost:2181",
new RetryNTimes(3, 1000)
);
client.start();
// 注册服务(临时节点)
String servicePath = "/services/user-service";
String instancePath = client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
.forPath(servicePath + "/instance", "10.0.0.1:8080".getBytes());
// 服务发现(监听节点变化)
List instances = client.getChildren()
.usingWatcher((CuratorWatcher) event -> {
System.out.println("Services changed: " + event.getPath());
})
.forPath(servicePath);
System.out.println("Available instances: " + instances);
}
}
四、Nacos
特点:
- 动态服务发现、配置管理、易于与 Spring Cloud 和 Kubernetes 集成。
服务注册(使用 Java SDK):
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class NacosExample {
public static void main(String[] args) throws Exception {
// 连接 Nacos
NamingService naming = NacosFactory.createNamingService("localhost:8848");
// 注册服务
Instance instance = new Instance();
instance.setIp("10.0.0.1");
instance.setPort(8080);
instance.setServiceName("user-service");
naming.registerInstance("user-service", instance);
// 服务发现
List instances = naming.selectInstances("user-service", true);
System.out.println("Available instances: " + instances);
}
}
HTTP API:
# 注册服务
curl -X POST http://localhost:8848/nacos/v1/ns/instance?serviceName=user-service&ip=10.0.0.1&port=8080
# 发现服务
curl http://localhost:8848/nacos/v1/ns/instance/list?serviceName=user-service
五、对比与选型建议
特性 | Consul | Etcd | Zookeeper | Nacos |
一致性协议 | Raft | Raft | ZAB | Raft/Distro |
健康检查 | 内置多种检查方式 | 无(需自行实现) | 无(需自行实现) | 内置健康检查 |
配置管理 | 支持 | 支持(KV 存储) | 支持(ZK 节点) | 支持 |
多数据中心 | 原生支持 | 不支持 | 不支持 | 支持 |
易用性 | 中等 | 中等 | 复杂 | 高(中文文档友好) |
适用场景 | 多数据中心、大规模微服务 | Kubernetes 生态 | 传统分布式系统 | Spring Cloud/云原生 |
选型建议:
- Kubernetes 环境:优先选择 Etcd(已默认集成)。
- 多数据中心需求:选择 Consul 或 Nacos。
- Spring Cloud 集成:Nacos(无缝兼容)或 Consul。
- 简单轻量级场景:Nacos(功能全面,学习成本低)。
- 传统分布式系统:Zookeeper(成熟但配置复杂)。
六、快速启动命令
Consul:
docker run -d --name=consul -p 8500:8500 consul agent -server -bootstrap -ui -client=0.0.0.0
Etcd:
docker run -d --name=etcd -p 2379:2379 quay.io/coreos/etcd:v3.5.0 etcd --advertise-client-urls=http://0.0.0.0:2379 --listen-client-urls=http://0.0.0.0:2379
Zookeeper:
docker run -d --name=zookeeper -p 2181:2181 zookeeper:3.8
Nacos:
docker run -d --name=nacos -p 8848:8848 nacos/nacos-server:v2.1.0
通过以上示例和对比,可根据具体需求选择最适合的服务注册与发现工具。