# 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` ```nginx 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` ```nginx # 上游服务定义 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` ```nginx 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` ```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` ```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` ```yaml 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` ```bash # 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 服务器准备 ```bash # 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 启动服务 ```bash # 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 验证部署 ```bash # 健康检查 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 日志 ```bash # 访问日志 tail -f /opt/rwadurian/nginx/logs/access.log # 错误日志 tail -f /opt/rwadurian/nginx/logs/error.log ``` ### 8.2 服务日志 ```bash # 查看特定服务日志 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