← 返回首页
🔍

服务发现与注册

📂 devops ⏱ 2 min 261 words

服务发现与注册

服务发现模式

模式 说明 工具
客户端发现 客户端查询注册表 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');

最佳实践

  1. 实现健康检查
  2. 使用TTL防止过期服务
  3. 实现客户端负载均衡
  4. 监控服务健康状态
  5. 实现优雅关闭

总结

服务发现是微服务架构的基础。通过Consul、etcd或Kubernetes内置的服务发现机制,可以实现动态的服务注册和发现。