服务发现与注册
服务发现与注册
服务发现模式
| 模式 | 说明 | 工具 |
|---|---|---|
| 客户端发现 | 客户端查询注册表 | Eureka |
| 服务端发现 | 负载均衡器查询 | Consul, etcd |
| DNS发现 | DNS解析 | CoreDNS |
Consul
安装Consul
# Docker
docker run -d --name consul \
-p 8500:8500 \
consul:agent -server -bootstrap -ui -client=0.0.0.0
# 访问UI
# http://localhost:8500
服务注册
{
"service": {
"name": "user-api",
"port": 8080,
"tags": ["v1", "production"],
"check": {
"http": "http://localhost:8080/health",
"interval": "10s",
"timeout": "5s"
}
}
}
服务发现
# HTTP API
curl http://localhost:8500/v1/catalog/service/user-api
# DNS查询
dig @127.0.0.1 -p 8600 user-api.service.consul
健康检查
# 查看健康状态
curl http://localhost:8500/v1/health/service/user-api
# 只返回健康实例
curl http://localhost:8500/v1/health/service/user-api?passing=true
etcd
安装etcd
# Docker
docker run -d --name etcd \
-p 2379:2379 \
quay.io/coreos/etcd etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2379
服务注册
# 注册服务
etcdctl put /services/user-api/instance1 '{"host":"10.0.1.1","port":8080}'
# 设置TTL
etcdctl put --lease=12345 /services/user-api/instance1 '{"host":"10.0.1.1","port":8080}'
服务发现
# 获取服务列表
etcdctl get /services/user-api --prefix
# 监听变更
etcdctl watch /services/user-api --prefix
Kubernetes服务发现
内置服务发现
# 服务定义
apiVersion: v1
kind: Service
metadata:
name: user-api
spec:
selector:
app: user-api
ports:
- port: 80
targetPort: 8080
DNS解析
# 集群内DNS
user-api # 同一命名空间
user-api.default # 指定命名空间
user-api.default.svc.cluster.local # 完整FQDN
实践:Consul服务网格
# docker-compose.yml
version: '3.8'
services:
consul:
image: consul:1.15
ports:
- "8500:8500"
command: agent -server -bootstrap -ui -client=0.0.0.0
api:
image: myapi
environment:
- CONSUL_HTTP_ADDR=consul:8500
- SERVICE_NAME=user-api
- SERVICE_PORT=8080
depends_on:
- consul
nginx:
image: nginx
volumes:
- ./nginx-consul-template:/etc/nginx/templates
depends_on:
- consul
Consul Template
# /etc/nginx/templates/api.conf.ctmpl
upstream api {
{{range service "user-api"}}
server {{.Address}}:{{.Port}};
{{end}}
}
server {
listen 80;
location / {
proxy_pass http://api;
}
}
客户端负载均衡
// Node.js示例
const consul = require('consul')({ host: 'consul' });
async function getServiceUrl(serviceName) {
const services = await consul.health.service(serviceName, { passing: true });
const service = services[Math.floor(Math.random() * services.length)];
return `http://${service.Service.Address}:${service.Service.Port}`;
}
// 使用
const url = await getServiceUrl('user-api');
最佳实践
- 实现健康检查
- 使用TTL防止过期服务
- 实现客户端负载均衡
- 监控服务健康状态
- 实现优雅关闭
总结
服务发现是微服务架构的基础。通过Consul、etcd或Kubernetes内置的服务发现机制,可以实现动态的服务注册和发现。