服务发现

服务发现

什么是服务发现

在容器化环境中,容器 IP 是动态分配的,每次重启都会变化。服务发现允许服务通过逻辑名称而非固定 IP 来找到彼此。

为什么容器环境需要服务发现

传统架构:             容器化架构:
user-service      user-service-1 (10.0.0.5)
  ↓ 固定 IP       用户请求 user-service
db: 192.168.1.5    ↓
                  DNS 解析 → 10.0.0.5
                  如果挂了,重新调度
                  user-service-2 (10.0.0.6)
                  IP 变了,但名称不变

Docker 内置服务发现

1. 默认 Bridge 网络

容器的通信只能通过 IP,不支持服务名解析。

2. 自定义网络(推荐)

# 创建自定义网络
docker network create myapp-net

# 在这个网络中的容器可以通过容器名通信
docker run -d --name db --network myapp-net postgres:15
docker run -d --name app --network myapp-net myapp:latest

# app 容器中可以直接访问
# ping db
# curl http://db:5432

3. Docker Compose

version: '3.8'
services:
  web:
    image: nginx
    depends_on:
      - api
  api:
    image: myapi:latest
    environment:
      DB_HOST: database    # 服务名 DNS
  database:
    image: postgres:15

Compose 自动为每个服务创建 DNS 记录,服务名即为主机名。

4. Docker Swarm

# Swarm 内置 DNS 和负载均衡
docker service create --name web --replicas 3 nginx

# 任何容器访问 web 都会被负载均衡到任意一个副本
docker service create --name consumer alpine \
  sh -c "while true; do wget -qO- http://web; done"

Kubernetes 服务发现

ClusterIP Service

apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - port: 8080

Pod 可以通过 user-serviceuser-service.namespace.svc.cluster.local 访问。

Headless Service

apiVersion: v1
kind: Service
metadata:
  name: stateful-service
spec:
  clusterIP: None
  selector:
    app: stateful

直接返回所有 Pod IP,适合有状态应用。

外部服务发现方案

1. Consul

# 启动 Consul
docker run -d \
  --name consul \
  -p 8500:8500 \
  consul:latest

# 注册服务
docker run -d \
  -e SERVICE_NAME=web \
  -e SERVICE_TAGS=prod \
  progrium/consul

2. etcd

# 启动 etcd
docker run -d \
  --name etcd \
  -p 2379:2379 \
  quay.io/coreos/etcd

# 注册服务
etcdctl put /services/web/1 '{"ip":"10.0.0.5","port":8080}'

3. ZooKeeper

# 创建节点
create /services/myapp "10.0.0.5:8080"

# 读取
get /services/myapp

服务发现的模式

客户端发现

客户端 → 服务注册表 → 获取 IP 列表 → 选择一个发起请求
  • 客户端需要集成服务发现逻辑
  • 优点:简单,没有中间层
  • 缺点:每个客户端需要实现发现逻辑

服务端发现

客户端 → 负载均衡器 → 转发到可用服务
  • 客户端只需访问一个地址
  • 优点:对客户端透明
  • 缺点:需要额外部署负载均衡器

面试要点

  1. Docker 自定义网络内置 DNS 服务发现:在同一网络中的容器可以通过容器名互相访问
  2. Swarm 和 Compose 天然支持服务名解析
  3. K8s 通过 Service 资源提供了 DNS 和服务发现
  4. 服务发现是微服务通信的基础设施
  5. 外部方案(Consul/etcd)适用于跨集群的场景

面试官常问:Docker 自定义网络的服务发现是怎么实现的?和 K8s 的 Service 有什么异同?

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容