微服务架构部署 #

微服务架构概述 #

架构图 #

text
┌─────────────────────────────────────────────────────┐
│                   微服务架构                         │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌─────────────────────────────────────────────┐   │
│  │              API Gateway                     │   │
│  │              (Kong/Nginx)                    │   │
│  └───────────────────┬─────────────────────────┘   │
│                      │                              │
│     ┌────────────────┼────────────────┐            │
│     │                │                │            │
│  ┌──▼───┐       ┌────▼───┐      ┌────▼───┐       │
│  │用户  │       │订单    │      │商品    │       │
│  │服务  │       │服务    │      │服务    │       │
│  └──┬───┘       └────┬───┘      └────┬───┘       │
│     │                │                │            │
│  ┌──▼───┐       ┌────▼───┐      ┌────▼───┐       │
│  │用户DB│       │订单DB  │      │商品DB  │       │
│  └──────┘       └────────┘      └────────┘       │
│                                                     │
│  ┌─────────────────────────────────────────────┐   │
│  │              Redis / MQ                      │   │
│  └─────────────────────────────────────────────┘   │
│                                                     │
└─────────────────────────────────────────────────────┘

项目结构 #

text
microservices/
├── docker-compose.yml
├── api-gateway/
│   ├── Dockerfile
│   └── nginx.conf
├── user-service/
│   ├── Dockerfile
│   └── src/
├── order-service/
│   ├── Dockerfile
│   └── src/
├── product-service/
│   ├── Dockerfile
│   └── src/
└── config/
    └── ...

API Gateway #

Dockerfile #

dockerfile
FROM nginx:alpine

COPY nginx.conf /etc/nginx/nginx.conf
COPY upstream.conf /etc/nginx/conf.d/upstream.conf

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

nginx.conf #

nginx
upstream user_service {
    server user-service:3001;
}

upstream order_service {
    server order-service:3002;
}

upstream product_service {
    server product-service:3003;
}

server {
    listen 80;
    
    location /api/users {
        proxy_pass http://user_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location /api/orders {
        proxy_pass http://order_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location /api/products {
        proxy_pass http://product_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

用户服务 #

Dockerfile #

dockerfile
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY src/ ./src/

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

EXPOSE 3001

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3001/health || exit 1

CMD ["node", "src/index.js"]

Docker Compose配置 #

docker-compose.yml #

yaml
version: '3.8'

services:
  # API Gateway
  api-gateway:
    build:
      context: ./api-gateway
      dockerfile: Dockerfile
    ports:
      - "80:80"
    networks:
      - frontend
    depends_on:
      - user-service
      - order-service
      - product-service
    restart: unless-stopped

  # 用户服务
  user-service:
    build:
      context: ./user-service
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DB_HOST=user-db
      - DB_PORT=3306
      - DB_NAME=user_db
      - REDIS_HOST=redis
    networks:
      - frontend
      - backend
    depends_on:
      - user-db
      - redis
    restart: unless-stopped
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # 订单服务
  order-service:
    build:
      context: ./order-service
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DB_HOST=order-db
      - DB_PORT=3306
      - DB_NAME=order_db
      - REDIS_HOST=redis
      - MQ_HOST=rabbitmq
    networks:
      - frontend
      - backend
    depends_on:
      - order-db
      - redis
      - rabbitmq
    restart: unless-stopped
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # 商品服务
  product-service:
    build:
      context: ./product-service
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DB_HOST=product-db
      - DB_PORT=3306
      - DB_NAME=product_db
      - REDIS_HOST=redis
    networks:
      - frontend
      - backend
    depends_on:
      - product-db
      - redis
    restart: unless-stopped
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # 用户数据库
  user-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: user_db
    volumes:
      - user-db-data:/var/lib/mysql
    networks:
      - backend
    restart: unless-stopped

  # 订单数据库
  order-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: order_db
    volumes:
      - order-db-data:/var/lib/mysql
    networks:
      - backend
    restart: unless-stopped

  # 商品数据库
  product-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: product_db
    volumes:
      - product-db-data:/var/lib/mysql
    networks:
      - backend
    restart: unless-stopped

  # Redis缓存
  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: unless-stopped

  # RabbitMQ消息队列
  rabbitmq:
    image: rabbitmq:3-management-alpine
    ports:
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - backend
    restart: unless-stopped

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  user-db-data:
  order-db-data:
  product-db-data:
  redis-data:
  rabbitmq-data:

服务发现 #

使用Consul #

yaml
# docker-compose.yml添加
services:
  consul:
    image: consul:latest
    ports:
      - "8500:8500"
    networks:
      - backend

服务注册 #

javascript
// 服务启动时注册到Consul
const Consul = require('consul');
const consul = new Consul();

consul.agent.service.register({
  name: 'user-service',
  address: process.env.SERVICE_ADDRESS,
  port: 3001,
  check: {
    http: `http://${process.env.SERVICE_ADDRESS}:3001/health`,
    interval: '10s'
  }
});

配置管理 #

使用配置中心 #

yaml
# docker-compose.yml添加
services:
  config-server:
    image: springcloud/configserver
    ports:
      - "8888:8888"
    networks:
      - backend

环境变量配置 #

yaml
# .env
NODE_ENV=production
DB_HOST=db
DB_PORT=3306
REDIS_HOST=redis
MQ_HOST=rabbitmq

监控和日志 #

Prometheus + Grafana #

yaml
# docker-compose.yml添加
services:
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - backend

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    networks:
      - backend

ELK日志收集 #

yaml
# docker-compose.yml添加
services:
  elasticsearch:
    image: elasticsearch:8.10.0
    environment:
      - discovery.type=single-node
    ports:
      - "9200:9200"
    networks:
      - backend

  logstash:
    image: logstash:8.10.0
    ports:
      - "5044:5044"
    networks:
      - backend

  kibana:
    image: kibana:8.10.0
    ports:
      - "5601:5601"
    networks:
      - backend

部署命令 #

bash
# 构建所有服务
docker-compose build

# 启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs -f

# 扩展服务
docker-compose up -d --scale user-service=3

# 停止所有服务
docker-compose down

# 清理数据
docker-compose down -v

小结 #

本节学习了微服务架构的容器化部署:

  • 微服务架构设计
  • API Gateway配置
  • 服务容器化
  • Docker Compose编排
  • 服务发现和配置管理
  • 监控和日志

下一步 #

接下来,让我们学习 CI/CD流水线集成,了解如何将Docker集成到CI/CD流程中。