20 KiB
20 KiB
Admin Service 部署文档
目录
1. 部署概述
1.1 部署架构
┌─────────────────────────────────────────────────┐
│ Load Balancer │
│ (Nginx / AWS ALB / etc.) │
└───────────────────┬─────────────────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Admin │ │ Admin │ │ Admin │
│ Service │ │ Service │ │ Service │
│ Instance │ │ Instance │ │ Instance │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└─────────────┼─────────────┘
│
▼
┌──────────────────┐
│ PostgreSQL │
│ (Primary + │
│ Replicas) │
└──────────────────┘
1.2 部署环境
| 环境 | 说明 | 数据库 | 实例数 |
|---|---|---|---|
| Development | 开发环境 | 本地/Docker | 1 |
| Staging | 预发布环境 | 独立数据库 | 1-2 |
| Production | 生产环境 | 高可用集群 | 3+ |
1.3 系统要求
最低配置
| 资源 | 要求 |
|---|---|
| CPU | 2 核心 |
| 内存 | 2 GB |
| 硬盘 | 20 GB (SSD) |
| 网络 | 100 Mbps |
推荐配置 (生产环境)
| 资源 | 要求 |
|---|---|
| CPU | 4 核心 |
| 内存 | 4-8 GB |
| 硬盘 | 50 GB (SSD) |
| 网络 | 1 Gbps |
2. 环境准备
2.1 服务器准备
# Ubuntu 22.04 LTS 示例
# 1. 更新系统
sudo apt update && sudo apt upgrade -y
# 2. 安装基础工具
sudo apt install -y \
curl \
wget \
git \
build-essential \
ca-certificates \
gnupg \
lsb-release
# 3. 安装 Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# 验证
node --version # v20.x.x
npm --version # 10.x.x
# 4. 安装 PM2 (进程管理器)
sudo npm install -g pm2
# 5. 安装 PostgreSQL 16
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo apt install -y postgresql-16
2.2 数据库配置
# 1. 切换到 postgres 用户
sudo -u postgres psql
# 2. 创建数据库和用户
CREATE DATABASE admin_service_prod;
CREATE USER admin_service WITH ENCRYPTED PASSWORD 'your_secure_password';
GRANT ALL PRIVILEGES ON DATABASE admin_service_prod TO admin_service;
# 3. 退出 psql
\q
# 4. 配置 PostgreSQL 允许远程连接 (如果需要)
sudo nano /etc/postgresql/16/main/postgresql.conf
# 修改: listen_addresses = '*'
sudo nano /etc/postgresql/16/main/pg_hba.conf
# 添加: host all all 0.0.0.0/0 md5
# 5. 重启 PostgreSQL
sudo systemctl restart postgresql
2.3 防火墙配置
# UFW 防火墙配置
sudo ufw allow 22/tcp # SSH
sudo ufw allow 3005/tcp # Admin Service (或通过 Nginx 反向代理)
sudo ufw allow 5432/tcp # PostgreSQL (仅内网)
sudo ufw enable
sudo ufw status
3. 本地部署
3.1 克隆代码
cd /opt
sudo git clone https://github.com/your-org/rwa-durian.git
cd rwa-durian/backend/services/admin-service
# 设置权限
sudo chown -R $USER:$USER /opt/rwa-durian
3.2 安装依赖
npm ci --omit=dev
3.3 环境配置
创建 .env.production:
# 应用配置
NODE_ENV=production
APP_PORT=3005
API_PREFIX=api/v1
# 数据库配置
DATABASE_URL=postgresql://admin_service:your_secure_password@localhost:5432/admin_service_prod?schema=public
# 日志配置
LOG_LEVEL=info
# CORS 配置
CORS_ORIGIN=https://admin.rwadurian.com,https://app.rwadurian.com
# 安全配置 (待实现)
JWT_SECRET=your_super_secret_jwt_key_change_in_production
3.4 数据库迁移
# 生成 Prisma Client
npm run prisma:generate
# 运行迁移
npm run prisma:migrate:deploy
# (可选) 运行初始化脚本
psql -U admin_service -d admin_service_prod -f database/init.sql
3.5 构建应用
npm run build
3.6 使用 PM2 启动
创建 ecosystem.config.js:
module.exports = {
apps: [
{
name: 'admin-service',
script: 'dist/main.js',
instances: 2, // CPU 核心数
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
APP_PORT: 3005,
},
env_file: '.env.production',
error_file: 'logs/error.log',
out_file: 'logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
merge_logs: true,
autorestart: true,
max_memory_restart: '500M',
watch: false,
},
],
};
启动服务:
# 启动
pm2 start ecosystem.config.js
# 查看状态
pm2 status
# 查看日志
pm2 logs admin-service
# 重启
pm2 restart admin-service
# 停止
pm2 stop admin-service
# 删除
pm2 delete admin-service
3.7 设置开机自启动
# 保存 PM2 进程列表
pm2 save
# 生成启动脚本
pm2 startup systemd
# 执行输出的命令 (类似):
# sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your_user --hp /home/your_user
3.8 验证部署
# 检查服务状态
curl http://localhost:3005/api/v1/health
# 预期响应
{"status": "ok"}
# 检查版本查询
curl http://localhost:3005/api/v1/version/check?platform=android&versionCode=1
# PM2 状态
pm2 status
4. Docker 部署
4.1 Dockerfile
Dockerfile:
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
# 安装 OpenSSL (Prisma 需要)
RUN apk add --no-cache openssl
# 复制 package.json 和 package-lock.json
COPY package*.json ./
COPY prisma ./prisma/
# 安装依赖
RUN npm ci
# 生成 Prisma Client
RUN npx prisma generate
# 复制源代码
COPY . .
# 构建
RUN npm run build
# 生产阶段
FROM node:20-alpine
WORKDIR /app
RUN apk add --no-cache openssl
# 复制依赖
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
# 暴露端口
EXPOSE 3005
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \
CMD wget -q --spider http://localhost:3005/api/v1/health || exit 1
# 启动命令
CMD ["node", "dist/main.js"]
4.2 Docker Compose
docker-compose.yml:
version: '3.8'
services:
admin-service:
build:
context: .
dockerfile: Dockerfile
container_name: admin-service
restart: unless-stopped
ports:
- "3005:3005"
environment:
- NODE_ENV=production
- APP_PORT=3005
- API_PREFIX=api/v1
- DATABASE_URL=postgresql://postgres:password@postgres:5432/admin_service_prod
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3005/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- admin-network
postgres:
image: postgres:16-alpine
container_name: admin-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=admin_service_prod
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 10
networks:
- admin-network
volumes:
postgres_data:
networks:
admin-network:
driver: bridge
4.3 Docker 部署步骤
# 1. 构建镜像
docker-compose build
# 2. 启动服务
docker-compose up -d
# 3. 运行数据库迁移
docker-compose exec admin-service npx prisma migrate deploy
# 4. 查看日志
docker-compose logs -f admin-service
# 5. 查看状态
docker-compose ps
# 6. 停止服务
docker-compose down
# 7. 清理 (包括数据)
docker-compose down -v
4.4 Docker 健康检查
# 检查容器健康状态
docker ps
# 查看健康检查日志
docker inspect admin-service | jq '.[0].State.Health'
# 手动健康检查
docker exec admin-service wget -q -O - http://localhost:3005/api/v1/health
5. 生产环境部署
5.1 Nginx 反向代理
安装 Nginx:
sudo apt install -y nginx
配置文件 (/etc/nginx/sites-available/admin-service):
upstream admin_service {
least_conn;
server 127.0.0.1:3005;
# server 127.0.0.1:3006; # 多实例负载均衡
# server 127.0.0.1:3007;
}
server {
listen 80;
listen [::]:80;
server_name admin-api.rwadurian.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name admin-api.rwadurian.com;
# SSL 证书
ssl_certificate /etc/letsencrypt/live/admin-api.rwadurian.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/admin-api.rwadurian.com/privkey.pem;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 日志
access_log /var/log/nginx/admin-service-access.log;
error_log /var/log/nginx/admin-service-error.log;
# 代理配置
location /api/v1/ {
proxy_pass http://admin_service;
proxy_http_version 1.1;
# 请求头
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓存禁用 (API 不需要)
proxy_cache_bypass $http_upgrade;
}
# 健康检查端点
location /health {
proxy_pass http://admin_service/api/v1/health;
access_log off;
}
}
启用配置:
sudo ln -s /etc/nginx/sites-available/admin-service /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
5.2 SSL 证书 (Let's Encrypt)
# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d admin-api.rwadurian.com
# 自动续期测试
sudo certbot renew --dry-run
# 自动续期 (crontab)
sudo crontab -e
# 添加: 0 3 * * * certbot renew --quiet
5.3 日志管理
日志轮转
创建 /etc/logrotate.d/admin-service:
/opt/rwa-durian/backend/services/admin-service/logs/*.log {
daily
rotate 30
compress
delaycompress
notifempty
create 0640 your_user your_user
sharedscripts
postrotate
pm2 reloadLogs
endscript
}
查看日志
# PM2 日志
pm2 logs admin-service
# 实时日志
pm2 logs admin-service --lines 100
# 错误日志
pm2 logs admin-service --err
# Nginx 日志
sudo tail -f /var/log/nginx/admin-service-access.log
sudo tail -f /var/log/nginx/admin-service-error.log
5.4 数据库备份
自动备份脚本
创建 /opt/scripts/backup-admin-db.sh:
#!/bin/bash
# 配置
DB_NAME="admin_service_prod"
DB_USER="admin_service"
BACKUP_DIR="/opt/backups/admin-service"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# 创建备份目录
mkdir -p $BACKUP_DIR
# 执行备份
pg_dump -U $DB_USER -d $DB_NAME -F c -b -v -f "$BACKUP_DIR/admin_service_$DATE.backup"
# 压缩
gzip "$BACKUP_DIR/admin_service_$DATE.backup"
# 删除旧备份
find $BACKUP_DIR -name "*.backup.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: admin_service_$DATE.backup.gz"
设置定时任务
chmod +x /opt/scripts/backup-admin-db.sh
# 添加到 crontab
crontab -e
# 每天凌晨 2 点备份
0 2 * * * /opt/scripts/backup-admin-db.sh >> /var/log/admin-service-backup.log 2>&1
恢复数据库
# 解压备份
gunzip admin_service_20250103_020000.backup.gz
# 恢复
pg_restore -U admin_service -d admin_service_prod -v admin_service_20250103_020000.backup
5.5 监控告警
PM2 监控
# 安装 PM2 Plus (可选)
pm2 install pm2-logrotate
pm2 install pm2-server-monit
# 查看监控
pm2 monit
健康检查脚本
创建 /opt/scripts/health-check.sh:
#!/bin/bash
HEALTH_URL="http://localhost:3005/api/v1/health"
ALERT_EMAIL="admin@rwadurian.com"
response=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)
if [ "$response" != "200" ]; then
echo "Admin Service health check failed! HTTP code: $response" | \
mail -s "Admin Service Alert" $ALERT_EMAIL
# 自动重启 (可选)
pm2 restart admin-service
fi
设置监控定时任务
crontab -e
# 每 5 分钟检查一次
*/5 * * * * /opt/scripts/health-check.sh
6. 监控和维护
6.1 性能监控
应用指标
# CPU 和内存使用
pm2 monit
# 详细指标
pm2 describe admin-service
# 进程列表
pm2 list
数据库监控
# 连接数
sudo -u postgres psql -c "SELECT count(*) FROM pg_stat_activity WHERE datname = 'admin_service_prod';"
# 慢查询
sudo -u postgres psql -d admin_service_prod -c "SELECT query, calls, total_time, mean_time FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 10;"
# 数据库大小
sudo -u postgres psql -c "SELECT pg_size_pretty(pg_database_size('admin_service_prod'));"
6.2 日常维护
更新应用
cd /opt/rwa-durian/backend/services/admin-service
# 1. 备份当前版本
cp -r dist dist.backup.$(date +%Y%m%d)
# 2. 拉取最新代码
git pull origin main
# 3. 安装依赖
npm ci --omit=dev
# 4. 运行迁移
npm run prisma:migrate:deploy
# 5. 构建
npm run build
# 6. 重启服务
pm2 restart admin-service
# 7. 验证
curl http://localhost:3005/api/v1/health
# 8. 查看日志
pm2 logs admin-service --lines 50
数据库维护
# 1. 分析表
sudo -u postgres psql -d admin_service_prod -c "ANALYZE;"
# 2. 清理死元组
sudo -u postgres psql -d admin_service_prod -c "VACUUM ANALYZE;"
# 3. 重建索引
sudo -u postgres psql -d admin_service_prod -c "REINDEX DATABASE admin_service_prod;"
6.3 扩容方案
垂直扩容 (增加资源)
# 1. 调整 PM2 实例数
pm2 scale admin-service 4 # 增加到 4 个实例
# 2. 调整内存限制
# 编辑 ecosystem.config.js
max_memory_restart: '1G' # 增加到 1GB
pm2 restart admin-service
水平扩容 (增加服务器)
- 在新服务器上重复本地部署步骤
- 配置 Nginx 负载均衡:
upstream admin_service {
least_conn;
server 192.168.1.10:3005 weight=1;
server 192.168.1.11:3005 weight=1;
server 192.168.1.12:3005 weight=1;
}
- 重新加载 Nginx:
sudo nginx -t
sudo systemctl reload nginx
7. 故障排查
7.1 常见问题
问题 1: 服务无法启动
症状:
pm2 logs admin-service
# Error: Cannot find module '@prisma/client'
解决方案:
npm run prisma:generate
pm2 restart admin-service
问题 2: 数据库连接失败
症状:
Error: P1001: Can't reach database server
排查步骤:
# 1. 检查 PostgreSQL 状态
sudo systemctl status postgresql
# 2. 测试数据库连接
psql -U admin_service -h localhost -d admin_service_prod
# 3. 检查 DATABASE_URL 配置
cat .env.production | grep DATABASE_URL
# 4. 检查防火墙
sudo ufw status
问题 3: 内存泄漏
症状:
pm2 list
# admin-service 内存持续增长
排查步骤:
# 1. 查看内存使用
pm2 describe admin-service
# 2. 分析堆内存
node --inspect dist/main.js
# 访问 chrome://inspect
# 3. 临时解决 - 重启
pm2 restart admin-service
# 4. 调整内存限制
# ecosystem.config.js
max_memory_restart: '500M'
问题 4: 高并发性能下降
症状: 响应时间变长,超时增加
优化方案:
- 增加实例数:
pm2 scale admin-service +2
- 数据库连接池:
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["metrics"]
}
// src/infrastructure/prisma/prisma.service.ts
@Injectable()
export class PrismaService extends PrismaClient {
constructor() {
super({
datasources: {
db: {
url: process.env.DATABASE_URL,
},
},
connectionLimit: 10, // 增加连接池
});
}
}
- 添加缓存 (Redis):
# 安装 Redis
sudo apt install -y redis-server
# 配置缓存
npm install @nestjs/cache-manager cache-manager cache-manager-redis-store
7.2 日志分析
错误日志
# 查看最近的错误
pm2 logs admin-service --err --lines 100
# 搜索特定错误
pm2 logs admin-service --err | grep "Error"
# Nginx 错误日志
sudo tail -100 /var/log/nginx/admin-service-error.log
性能分析
# PM2 性能监控
pm2 monit
# Node.js profiler
node --prof dist/main.js
# 生成 isolate-*.log
# 分析 profile
node --prof-process isolate-*.log > profile.txt
7.3 回滚策略
应用回滚
# 1. 停止服务
pm2 stop admin-service
# 2. 恢复备份代码
rm -rf dist
mv dist.backup.20250103 dist
# 3. 回滚数据库迁移 (谨慎!)
DATABASE_URL="..." npx prisma migrate resolve --rolled-back 20250103100000_add_new_field
# 4. 重启服务
pm2 start admin-service
# 5. 验证
curl http://localhost:3005/api/v1/health
数据库回滚
# 恢复数据库备份
pg_restore -U admin_service -d admin_service_prod -c admin_service_20250103_020000.backup
8. 安全加固
8.1 应用安全
# 1. 限制 Node.js 进程权限
# 创建专用用户
sudo useradd -r -s /bin/false admin_service
# 2. 设置文件权限
sudo chown -R admin_service:admin_service /opt/rwa-durian/backend/services/admin-service
sudo chmod -R 750 /opt/rwa-durian/backend/services/admin-service
# 3. 使用环境变量管理敏感信息
# .env.production 权限
chmod 600 .env.production
8.2 数据库安全
# 1. 修改默认密码
sudo -u postgres psql
ALTER USER admin_service WITH PASSWORD 'new_strong_password';
# 2. 限制网络访问
# /etc/postgresql/16/main/pg_hba.conf
host admin_service_prod admin_service 127.0.0.1/32 md5
# 3. 启用 SSL
# postgresql.conf
ssl = on
8.3 Nginx 安全
# 隐藏版本号
server_tokens off;
# 限流
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
# ...
location /api/v1/ {
limit_req zone=api_limit burst=20;
proxy_pass http://admin_service;
}
}
9. 快速参考
9.1 常用命令
# PM2 管理
pm2 start admin-service
pm2 stop admin-service
pm2 restart admin-service
pm2 reload admin-service # 零停机重启
pm2 delete admin-service
pm2 logs admin-service
pm2 monit
# 数据库
npm run prisma:migrate:deploy
npm run prisma:generate
npm run prisma:studio
# 构建
npm run build
npm run start:prod
# 健康检查
curl http://localhost:3005/api/v1/health
# Nginx
sudo systemctl status nginx
sudo systemctl reload nginx
sudo nginx -t
9.2 检查清单
部署前
- 代码已通过所有测试
- 环境变量已正确配置
- 数据库迁移已准备
- SSL 证书已配置
- 备份策略已设置
- 监控告警已配置
部署后
- 服务健康检查通过
- 数据库连接正常
- API 端点可访问
- 日志正常输出
- 性能指标正常
- 备份自动执行
最后更新: 2025-12-03 版本: 1.0.0 维护者: RWA Durian Team