SpringBoot + Dubbo + ZooKeeper 的 Docker Compose 部署方案

下面我将详细解释如何使用 Docker Compose 部署基于 SpringBoot、Dubbo 和 ZooKeeper 的微服务系统。

一、整体架构设计

 

二、项目目录结构

dubbo-project/
├── docker-compose.yml
├── .env                     # 环境变量文件
├── zookeeper/
│   ├── conf/
│   │   └── zoo.cfg          # ZK 配置文件
│   └── data/                # ZK 数据目录
├── service-user/            # 用户服务
│   ├── Dockerfile
│   ├── target/service-user.jar
│   └── config/
│       └── application.yml
├── service-order/           # 订单服务
│   ├── Dockerfile
│   ├── target/service-order.jar
│   └── config/
│       └── application.yml
├── service-gateway/         # API网关
│   ├── Dockerfile
│   ├── target/service-gateway.jar
│   └── config/
│       └── application.yml
└── mysql/
    ├── init.sql             # 数据库初始化脚本
    └── conf/
        └── my.cnf           # MySQL 配置文件

三、核心配置文件详解

1. .env 环境变量文件

# 公共环境变量
DUBBO_REGISTRY_ADDRESS=zookeeper://zk:2181
SPRING_PROFILES_ACTIVE=prod
TZ=Asia/Shanghai

# MySQL 配置
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=dubbo_db

# 服务端口
GATEWAY_PORT=8080
USER_SERVICE_PORT=20880
ORDER_SERVICE_PORT=20881

2. docker-compose.yml 完整配置

version: '3.8'

networks:
  dubbo-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

services:
  # ZooKeeper 注册中心
  zk:
    image: zookeeper:3.8
    container_name: zookeeper
    hostname: zookeeper
    ports:
      - "2181:2181"
      - "2888:2888"
      - "3888:3888"
    volumes:
      - ./zookeeper/data:/data
      - ./zookeeper/conf/zoo.cfg:/conf/zoo.cfg
      - ./zookeeper/logs:/datalog
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=zookeeper:2888:3888;2181
    networks:
      - dubbo-net
    healthcheck:
      test: ["CMD", "zkOk.sh"]
      interval: 10s
      timeout: 5s
      retries: 6

  # MySQL 数据库
  mysql:
    image: mysql:8.0
    container_name: mysql
    hostname: mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      TZ: ${TZ}
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
      - ./mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
    networks:
      - dubbo-net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 10

  # 用户服务
  service-user:
    build:
      context: ./service-user
    container_name: service-user
    hostname: service-user
    depends_on:
      zk:
        condition: service_healthy
      mysql:
        condition: service_healthy
    environment:
      DUBBO_REGISTRY_ADDRESS: ${DUBBO_REGISTRY_ADDRESS}
      DUBBO_PROVIDER_HOST: service-user  # 关键配置
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
      TZ: ${TZ}
    ports:
      - "${USER_SERVICE_PORT}:20880"
    networks:
      - dubbo-net
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:20880/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # 订单服务
  service-order:
    build:
      context: ./service-order
    container_name: service-order
    hostname: service-order
    depends_on:
      zk:
        condition: service_healthy
      mysql:
        condition: service_healthy
    environment:
      DUBBO_REGISTRY_ADDRESS: ${DUBBO_REGISTRY_ADDRESS}
      DUBBO_PROVIDER_HOST: service-order  # 关键配置
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
      TZ: ${TZ}
    ports:
      - "${ORDER_SERVICE_PORT}:20881"
    networks:
      - dubbo-net
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:20881/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # API网关
  service-gateway:
    build:
      context: ./service-gateway
    container_name: service-gateway
    hostname: service-gateway
    depends_on:
      service-user:
        condition: service_healthy
      service-order:
        condition: service_healthy
    environment:
      DUBBO_REGISTRY_ADDRESS: ${DUBBO_REGISTRY_ADDRESS}
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
      TZ: ${TZ}
    ports:
      - "${GATEWAY_PORT}:8080"
    networks:
      - dubbo-net
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3

3. Dubbo 服务配置示例 (service-user)

service-user/config/application.yml:

dubbo:
  application:
    name: service-user
  protocol:
    name: dubbo
    port: 20880
  registry:
    address: ${DUBBO_REGISTRY_ADDRESS}
  provider:
    host: ${DUBBO_PROVIDER_HOST}  # 使用容器名注册
    check: true
  consumer:
    check: false

spring:
  datasource:
    url: jdbc:mysql://mysql:3306/${MYSQL_DATABASE}?useSSL=false&characterEncoding=utf8
    username: root
    password: ${MYSQL_ROOT_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver

server:
  port: 20880

4. Dockerfile 示例 (所有服务通用)

# 使用带JRE的Alpine基础镜像
FROM eclipse-temurin:17-jre-alpine

# 设置时区
RUN apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

# 创建工作目录
WORKDIR /app

# 复制JAR文件和配置文件
COPY target/*.jar app.jar
COPY config/ /app/config/

# 设置健康检查端点(可选)
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
    CMD curl -f http://localhost:${SERVER_PORT:-20880}/health || exit 1

# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=/app/config/"]

5. ZooKeeper 配置文件 (zoo.cfg)

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data
dataLogDir=/datalog
clientPort=2181
maxClientCnxns=100
autopurge.snapRetainCount=3
autopurge.purgeInterval=1

四、关键问题解决方案

1. 服务注册IP问题(核心问题)

问题:默认Dubbo会使用容器内部IP注册,导致其他服务无法访问
解决方案:

 
# docker-compose.yml中
environment:
  DUBBO_PROVIDER_HOST: service-user  # 强制使用容器名注册

# application.yml中
dubbo:
  provider:
    host: ${DUBBO_PROVIDER_HOST}

2. 服务启动顺序控制

depends_on:
  zk:
    condition: service_healthy
  mysql:
    condition: service_healthy

3. 健康检查配置

healthcheck:
  # Dubbo服务健康检查
  test: ["CMD", "curl", "-f", "http://localhost:20880/health"]
  interval: 30s
  timeout: 10s
  retries: 3

4. 网络配置

networks:
  dubbo-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

五、部署流程

  1. 构建项目:

    # 构建所有服务
    mvn clean package -DskipTests
  2. 启动服务:

    docker-compose up -d --build
  3. 验证服务:

    # 查看服务状态
    docker-compose ps
    
    # 检查ZooKeeper注册情况
    docker exec -it zookeeper zkCli.sh ls /dubbo
    
    # 测试API网关
    curl http://localhost:8080/user/1
  4. 查看日志:

    docker-compose logs -f service-user

六、生产环境优化建议

1. ZooKeeper集群配置

services:
  zk1:
    image: zookeeper:3.8
    hostname: zk1
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181

  zk2:
    image: zookeeper:3.8
    hostname: zk2
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181

  zk3:
    image: zookeeper:3.8
    hostname: zk3
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181

2. 资源限制

service-user:
  deploy:
    resources:
      limits:
        cpus: '1.0'
        memory: 1G
      reservations:
        memory: 512M

3. 日志管理

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

4. Dubbo QoS控制

dubbo:
  application:
    qos-enable: true
    qos-port: 22222
    qos-accept-foreign-ip: false

七、常见问题排查

  1. 服务未注册到ZooKeeper:

    • 检查DUBBO_REGISTRY_ADDRESS环境变量

    • 确认ZooKeeper健康状态:docker-compose logs zookeeper

    • 查看服务日志:docker-compose logs service-user

  2. 服务调用超时:

    • 确认服务健康状态:docker-compose ps

    • 检查网络连通性:docker exec -it service-gateway ping service-user

    • 增加Dubbo超时时间:

      dubbo:
        consumer:
          timeout: 5000
  3. 数据库连接问题:

    • 检查MySQL容器状态

    • 确认连接URL:jdbc:mysql://mysql:3306/dubbo_db

    • 验证MySQL日志:docker-compose logs mysql

此配置方案解决了Dubbo在Docker环境中的核心问题(服务注册IP问题),并通过健康检查、网络隔离、资源限制等机制确保了生产环境的稳定性和可靠性。

posted @ 2025-06-29 11:06  郭慕荣  阅读(72)  评论(0)    收藏  举报