rwadurian/backend/services/identity-service/DEPLOYMENT_GUIDE.md

26 KiB

RWA Durian 系统部署指南

本文档描述了 RWA Durian 系统的完整部署架构,包括前端 API 调用、Nginx 反向代理配置和后端服务部署。

1. 系统架构概览

┌─────────────────────────────────────────────────────────────────────────────┐
│                              用户设备                                        │
│                         (Android/iOS App)                                    │
└─────────────────────────────────┬───────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                    https://rwaapi.szaiai.com                                 │
│                         (Nginx 反向代理)                                      │
│                                                                              │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐            │
│  │  /identity  │ │   /wallet   │ │  /planting  │ │  /referral  │  ...       │
│  └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘            │
└─────────┼───────────────┼───────────────┼───────────────┼───────────────────┘
          │               │               │               │
          ▼               ▼               ▼               ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           Docker Network                                     │
│                                                                              │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐            │
│  │  Identity   │ │   Wallet    │ │  Planting   │ │  Referral   │  ...       │
│  │   :3000     │ │   :3002     │ │   :3003     │ │   :3004     │            │
│  └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘            │
│                                                                              │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐                            │
│  │  PostgreSQL │ │    Redis    │ │    Kafka    │                            │
│  │   :5432     │ │   :6379     │ │   :9092     │                            │
│  └─────────────┘ └─────────────┘ └─────────────┘                            │
└─────────────────────────────────────────────────────────────────────────────┘

2. 后端服务端口规划

服务名称 端口 API 前缀 说明
Identity Service 3000 /api/v1 用户身份、认证、钱包创建
MPC Service 3001 /api/v1 MPC 密钥分片管理
Wallet Service 3002 /api/v1 钱包余额、交易
Planting Service 3003 /api/v1 认种业务
Referral Service 3004 /api/v1 推荐关系、分享
Reward Service 3005 /api/v1 挖矿奖励、收益
Authorization Service 3006 /api/v1 权限管理
Leaderboard Service 3007 /api 排行榜
Reporting Service 3008 /api/v1 遥测统计、报表
Backup Service 3009 - MPC 备份 (内部服务)

3. Nginx 配置

3.1 主配置文件 /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json application/javascript
               application/xml application/xml+rss text/javascript;

    # 限流配置
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    include /etc/nginx/conf.d/*.conf;
}

3.2 API 网关配置 /etc/nginx/conf.d/rwaapi.conf

# 上游服务定义
upstream identity_service {
    server identity-service:3000;
    keepalive 32;
}

upstream wallet_service {
    server wallet-service:3002;
    keepalive 32;
}

upstream planting_service {
    server planting-service:3003;
    keepalive 32;
}

upstream referral_service {
    server referral-service:3004;
    keepalive 32;
}

upstream reward_service {
    server reward-service:3005;
    keepalive 32;
}

upstream leaderboard_service {
    server leaderboard-service:3007;
    keepalive 32;
}

upstream reporting_service {
    server reporting-service:3008;
    keepalive 32;
}

server {
    listen 80;
    server_name rwaapi.szaiai.com;

    # 强制 HTTPS 重定向
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name rwaapi.szaiai.com;

    # SSL 证书配置
    ssl_certificate /etc/nginx/ssl/rwaapi.szaiai.com.pem;
    ssl_certificate_key /etc/nginx/ssl/rwaapi.szaiai.com.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # 现代 SSL 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    # 安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # CORS 配置
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;

    # 处理 OPTIONS 预检请求
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }

    # 限流
    limit_req zone=api_limit burst=20 nodelay;
    limit_conn conn_limit 10;

    # 健康检查端点
    location /health {
        access_log off;
        return 200 'OK';
        add_header Content-Type text/plain;
    }

    # ============================================
    # Identity Service - 用户身份认证
    # ============================================
    location /api/v1/user {
        proxy_pass http://identity_service/api/v1/user;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/auth {
        proxy_pass http://identity_service/api/v1/auth;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Wallet Service - 钱包操作
    # ============================================
    location /api/v1/wallet {
        proxy_pass http://wallet_service/api/v1/wallet;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/trading {
        proxy_pass http://wallet_service/api/v1/trading;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/deposit {
        proxy_pass http://wallet_service/api/v1/deposit;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Planting Service - 认种业务
    # ============================================
    location /api/v1/planting {
        proxy_pass http://planting_service/api/v1/planting;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Referral Service - 推荐系统
    # ============================================
    location /api/v1/referral {
        proxy_pass http://referral_service/api/v1/referral;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/community {
        proxy_pass http://referral_service/api/v1/community;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Reward Service - 挖矿奖励
    # ============================================
    location /api/v1/mining {
        proxy_pass http://reward_service/api/v1/mining;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/reward {
        proxy_pass http://reward_service/api/v1/reward;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Leaderboard Service - 排行榜
    # ============================================
    location /api/v1/ranking {
        proxy_pass http://leaderboard_service/api/ranking;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/leaderboard {
        proxy_pass http://leaderboard_service/api/leaderboard;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # ============================================
    # Reporting Service - 遥测统计
    # ============================================
    location /api/v1/telemetry {
        proxy_pass http://reporting_service/api/v1/telemetry;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    location /api/v1/report {
        proxy_pass http://reporting_service/api/v1/report;
        include /etc/nginx/conf.d/proxy_params.conf;
    }

    # 默认 404
    location / {
        return 404 '{"error": "Not Found", "message": "API endpoint not found"}';
        add_header Content-Type application/json;
    }
}

3.3 代理参数配置 /etc/nginx/conf.d/proxy_params.conf

proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";

proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;

4. 前端配置修改

4.1 修改 API 端点配置

文件: frontend/mobile-app/lib/core/constants/api_endpoints.dart

class ApiEndpoints {
  ApiEndpoints._();

  // Base URL - 生产环境
  static const String baseUrl = 'https://rwaapi.szaiai.com';

  // Base URL - 开发环境 (可选)
  static const String baseUrlDev = 'https://rwaapi-dev.szaiai.com';

  // API 版本前缀
  static const String apiPrefix = '/api/v1';

  // Auth & User (-> Identity Service)
  static const String user = '$apiPrefix/user';
  static const String auth = '$apiPrefix/auth';
  static const String autoCreate = '$user/auto-create';
  static const String login = '$auth/login';
  static const String refreshToken = '$auth/refresh';
  static const String logout = '$auth/logout';
  static const String profile = '$user/profile';

  // Wallet (-> Wallet Service)
  static const String wallet = '$apiPrefix/wallet';
  static const String balance = '$wallet/balance';
  static const String createWallet = '$wallet/create';
  static const String importWallet = '$wallet/import';

  // Trading (-> Wallet Service)
  static const String trading = '$apiPrefix/trading';
  static const String exchange = '$trading/exchange';
  static const String settlement = '$trading/settlement';
  static const String transactions = '$trading/transactions';

  // Deposit (-> Wallet Service)
  static const String deposit = '$apiPrefix/deposit';
  static const String depositAddress = '$deposit/address';
  static const String confirmDeposit = '$deposit/confirm';

  // Mining & Reward (-> Reward Service)
  static const String mining = '$apiPrefix/mining';
  static const String miningStatus = '$mining/status';
  static const String startMining = '$mining/start';
  static const String stopMining = '$mining/stop';
  static const String claimReward = '$mining/claim';
  static const String hashPower = '$mining/hash-power';

  // Ranking (-> Leaderboard Service)
  static const String ranking = '$apiPrefix/ranking';
  static const String dailyRanking = '$ranking/daily';
  static const String weeklyRanking = '$ranking/weekly';
  static const String monthlyRanking = '$ranking/monthly';

  // Planting (-> Planting Service)
  static const String planting = '$apiPrefix/planting';
  static const String plantingPrice = '$planting/price';
  static const String submitPlanting = '$planting/submit';

  // Community & Referral (-> Referral Service)
  static const String community = '$apiPrefix/community';
  static const String referral = '$apiPrefix/referral';
  static const String referralList = '$community/referrals';
  static const String earnings = '$community/earnings';
  static const String generateReferralLink = '$referral/generate-link';

  // Telemetry (-> Reporting Service)
  static const String telemetry = '$apiPrefix/telemetry';
  static const String telemetrySession = '$telemetry/session';
  static const String telemetryHeartbeat = '$telemetry/heartbeat';
  static const String telemetryEvents = '$telemetry/events';
}

4.2 修改 API 客户端默认 URL

文件: frontend/mobile-app/lib/core/network/api_client.dart

// 修改默认 Base URL
static const String _defaultBaseUrl = 'https://rwaapi.szaiai.com';

// 开发模式可使用本地地址
// static const String _defaultBaseUrl = 'http://10.0.2.2:3000'; // Android 模拟器
// static const String _defaultBaseUrl = 'http://localhost:3000'; // iOS 模拟器

5. Docker Compose 部署

5.1 主部署文件 docker-compose.prod.yml

services:
  # ============================================
  # Nginx API Gateway
  # ============================================
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - ./nginx/logs:/var/log/nginx
    depends_on:
      - identity-service
      - wallet-service
      - planting-service
      - referral-service
      - reward-service
      - leaderboard-service
      - reporting-service
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Identity Service
  # ============================================
  identity-service:
    build: ./services/identity-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_identity
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Wallet Service
  # ============================================
  wallet-service:
    build: ./services/wallet-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_wallet
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Planting Service
  # ============================================
  planting-service:
    build: ./services/planting-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_planting
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Referral Service
  # ============================================
  referral-service:
    build: ./services/referral-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_referral
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Reward Service
  # ============================================
  reward-service:
    build: ./services/reward-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_reward
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Leaderboard Service
  # ============================================
  leaderboard-service:
    build: ./services/leaderboard-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_leaderboard
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # Reporting Service
  # ============================================
  reporting-service:
    build: ./services/reporting-service
    environment:
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/rwa_reporting
      - JWT_SECRET=${JWT_SECRET}
      - REDIS_HOST=redis
      - KAFKA_BROKERS=kafka:29092
      - APP_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - rwa-network
    restart: unless-stopped

  # ============================================
  # 基础设施
  # ============================================
  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_MULTIPLE_DATABASES=rwa_identity,rwa_wallet,rwa_planting,rwa_referral,rwa_reward,rwa_leaderboard,rwa_reporting
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./scripts/init-multi-db.sh:/docker-entrypoint-initdb.d/init-multi-db.sh
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - rwa-network
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - rwa-network
    restart: unless-stopped

  zookeeper:
    image: confluentinc/cp-zookeeper:7.5.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
    networks:
      - rwa-network
    restart: unless-stopped

  kafka:
    image: confluentinc/cp-kafka:7.5.0
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT_INTERNAL://kafka:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT_INTERNAL:PLAINTEXT
      KAFKA_LISTENERS: PLAINTEXT_INTERNAL://0.0.0.0:29092
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT_INTERNAL
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    networks:
      - rwa-network
    restart: unless-stopped

networks:
  rwa-network:
    driver: bridge

volumes:
  postgres_data:
  redis_data:

5.2 环境变量文件 .env.prod

# Database
DB_PASSWORD=your_secure_database_password

# JWT
JWT_SECRET=your_super_secure_jwt_secret_at_least_32_chars

# Redis
REDIS_PASSWORD=your_secure_redis_password

# Wallet Encryption
WALLET_ENCRYPTION_SALT=your_wallet_encryption_salt

# Service JWT (for inter-service communication)
SERVICE_JWT_SECRET=your_service_jwt_secret

6. 部署步骤

6.1 服务器准备

# 1. 安装 Docker 和 Docker Compose
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

# 2. 创建部署目录
mkdir -p /opt/rwadurian
cd /opt/rwadurian

# 3. 克隆代码
git clone https://github.com/your-org/rwadurian.git .

# 4. 创建 Nginx 配置目录
mkdir -p nginx/{conf.d,ssl,logs}

# 5. 复制 Nginx 配置
cp docs/nginx/* nginx/

# 6. 安装 SSL 证书 (使用 Let's Encrypt 或购买的证书)
# 将证书放到 nginx/ssl/ 目录

6.2 启动服务

# 1. 复制并配置环境变量
cp .env.example .env.prod
vim .env.prod  # 修改为生产环境配置

# 2. 启动所有服务
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d

# 3. 查看服务状态
docker compose -f docker-compose.prod.yml ps

# 4. 查看日志
docker compose -f docker-compose.prod.yml logs -f

# 5. 运行数据库迁移
docker compose -f docker-compose.prod.yml exec identity-service npx prisma migrate deploy
docker compose -f docker-compose.prod.yml exec wallet-service npx prisma migrate deploy
# ... 其他服务

6.3 验证部署

# 健康检查
curl https://rwaapi.szaiai.com/health

# 测试 API
curl https://rwaapi.szaiai.com/api/v1/user/auto-create \
  -H "Content-Type: application/json" \
  -d '{"deviceId": "test-device-123"}'

7. API 端点对照表

前端调用 Nginx 路由 后端服务 服务端口
/api/v1/user/* /api/v1/user Identity Service 3000
/api/v1/auth/* /api/v1/auth Identity Service 3000
/api/v1/wallet/* /api/v1/wallet Wallet Service 3002
/api/v1/trading/* /api/v1/trading Wallet Service 3002
/api/v1/deposit/* /api/v1/deposit Wallet Service 3002
/api/v1/mining/* /api/v1/mining Reward Service 3005
/api/v1/ranking/* /api/v1/ranking Leaderboard Service 3007
/api/v1/planting/* /api/v1/planting Planting Service 3003
/api/v1/referral/* /api/v1/referral Referral Service 3004
/api/v1/community/* /api/v1/community Referral Service 3004
/api/v1/telemetry/* /api/v1/telemetry Reporting Service 3008

8. 监控与日志

8.1 Nginx 日志

# 访问日志
tail -f /opt/rwadurian/nginx/logs/access.log

# 错误日志
tail -f /opt/rwadurian/nginx/logs/error.log

8.2 服务日志

# 查看特定服务日志
docker compose -f docker-compose.prod.yml logs -f identity-service

# 查看所有服务日志
docker compose -f docker-compose.prod.yml logs -f

9. 常见问题

Q1: 502 Bad Gateway

  • 检查后端服务是否正常运行
  • 检查 Nginx upstream 配置的服务名是否正确
  • 检查 Docker 网络是否正确连接

Q2: CORS 错误

  • 确认 Nginx 配置中 CORS 头已正确设置
  • 确认 OPTIONS 预检请求处理正确

Q3: SSL 证书问题

  • 检查证书文件路径和权限
  • 确认证书未过期
  • 使用 openssl s_client -connect rwaapi.szaiai.com:443 测试

最后更新: 2025-12-01 维护者: RWA Team