# GameGroup 后端部署指导文档 ## 目录 - [环境准备](#环境准备) - [本地开发部署](#本地开发部署) - [生产环境部署](#生产环境部署) - [数据库配置](#数据库配置) - [性能优化建议](#性能优化建议) - [监控和维护](#监控和维护) - [常见问题排查](#常见问题排查) --- ## 环境准备 ### 系统要求 - **Node.js**: 18.x 或更高版本 - **MySQL**: 8.0 或更高版本 - **内存**: 最低 2GB RAM,推荐 4GB+ - **存储**: 最低 10GB 可用空间 ### 必需软件 ```bash # 检查 Node.js 版本 node --version # 应该 >= 18.0.0 # 检查 npm 版本 npm --version # 检查 MySQL 版本 mysql --version # 应该 >= 8.0 ``` --- ## 本地开发部署 ### 1. 克隆项目并安装依赖 ```bash # 进入项目目录 cd d:\vscProg\backend # 安装依赖 npm install ``` ### 2. 配置环境变量 复制环境变量示例文件: ```bash cp .env.example .env.development ``` 编辑 `.env.development` 文件: ```env # 应用配置 NODE_ENV=development PORT=3000 # 数据库配置 DB_TYPE=mysql DB_HOST=localhost DB_PORT=3306 DB_USERNAME=root DB_PASSWORD=你的数据库密码 DB_DATABASE=gamegroup DB_SYNCHRONIZE=true DB_LOGGING=true # JWT配置 JWT_SECRET=dev-secret-key-change-in-production JWT_EXPIRES_IN=7d # CORS配置 CORS_ORIGIN=http://localhost:8080 # 日志配置 LOG_LEVEL=debug # 缓存配置 CACHE_TTL=300 CACHE_MAX=100 # 性能配置 ENABLE_COMPRESSION=true QUERY_LIMIT=100 QUERY_TIMEOUT=30000 ``` ### 3. 创建数据库 ```bash # 登录 MySQL mysql -u root -p # 创建数据库 CREATE DATABASE gamegroup CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 创建用户(可选) CREATE USER 'gamegroup'@'localhost' IDENTIFIED BY 'your_password'; GRANT ALL PRIVILEGES ON gamegroup.* TO 'gamegroup'@'localhost'; FLUSH PRIVILEGES; EXIT; ``` ### 4. 启动开发服务器 ```bash # 启动开发模式(支持热重载) npm run start:dev # 或者普通启动 npm run start ``` 访问 http://localhost:3000 查看应用是否正常运行。 访问 http://localhost:3000/docs 查看 Swagger API 文档。 ### 5. 运行测试 ```bash # 运行所有测试 npm test # 运行测试并生成覆盖率报告 npm run test:cov # 监听模式运行测试 npm run test:watch ``` --- ## 生产环境部署 ### 方式一:Docker 部署(推荐) #### 1. 准备配置文件 创建 `.env.production` 文件: ```env NODE_ENV=production PORT=3000 # 数据库配置(使用强密码!) DB_HOST=mysql DB_PORT=3306 DB_USERNAME=gamegroup DB_PASSWORD=生产环境强密码 DB_DATABASE=gamegroup DB_SYNCHRONIZE=false DB_LOGGING=false DB_ROOT_PASSWORD=MySQL_Root强密码 # JWT配置(必须更换!) JWT_SECRET=生产环境超长随机密钥_至少32位 JWT_EXPIRES_IN=7d # CORS配置(限制为实际前端域名) CORS_ORIGIN=https://your-frontend-domain.com # 日志配置 LOG_LEVEL=info # 缓存配置 CACHE_TTL=600 CACHE_MAX=1000 # 性能配置 ENABLE_COMPRESSION=true QUERY_LIMIT=100 QUERY_TIMEOUT=30000 ``` #### 2. 构建和启动 ```bash # 构建生产镜像 docker-compose -f docker-compose.prod.yml build # 启动服务(后台运行) docker-compose -f docker-compose.prod.yml up -d # 查看运行状态 docker-compose -f docker-compose.prod.yml ps # 查看日志 docker-compose -f docker-compose.prod.yml logs -f backend ``` #### 3. 健康检查 ```bash # 检查应用健康状态 curl http://localhost:3000/health # 检查容器状态 docker ps # 查看容器资源使用 docker stats ``` #### 4. 停止服务 ```bash # 停止服务 docker-compose -f docker-compose.prod.yml down # 停止服务并删除数据卷(谨慎使用!) docker-compose -f docker-compose.prod.yml down -v ``` ### 方式二:PM2 部署 #### 1. 安装 PM2 ```bash npm install -g pm2 ``` #### 2. 构建应用 ```bash # 安装生产依赖 npm ci --only=production # 构建项目 npm run build:prod ``` #### 3. 启动应用 ```bash # 使用 PM2 启动 pm2 start ecosystem.config.js --env production # 查看运行状态 pm2 status # 查看日志 pm2 logs gamegroup-backend # 查看实时监控 pm2 monit ``` #### 4. 设置开机自启 ```bash # 保存当前 PM2 进程列表 pm2 save # 设置开机自启 pm2 startup # 根据提示执行相应命令(会因系统而异) ``` #### 5. 常用 PM2 命令 ```bash # 重启应用 pm2 restart gamegroup-backend # 停止应用 pm2 stop gamegroup-backend # 删除应用 pm2 delete gamegroup-backend # 重载应用(零停机重启) pm2 reload gamegroup-backend # 查看详细信息 pm2 show gamegroup-backend # 清空日志 pm2 flush ``` ### 方式三:直接使用 Node.js #### 1. 构建应用 ```bash npm run build:prod ``` #### 2. 启动应用 ```bash # 设置环境变量并启动 export NODE_ENV=production node dist/main.js # 或使用 npm 脚本 npm run start:prod ``` > ⚠️ **不推荐直接使用 Node.js**,因为没有进程管理和自动重启功能。 --- ## 数据库配置 ### 创建生产数据库 ```sql -- 创建数据库 CREATE DATABASE gamegroup CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建专用用户 CREATE USER 'gamegroup'@'%' IDENTIFIED BY '强密码'; -- 授予权限 GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER ON gamegroup.* TO 'gamegroup'@'%'; FLUSH PRIVILEGES; ``` ### 性能优化索引 ```sql USE gamegroup; -- 用户表索引 CREATE INDEX idx_user_username ON user(username); CREATE INDEX idx_user_email ON user(email); CREATE INDEX idx_user_phone ON user(phone); CREATE INDEX idx_user_is_member ON user(isMember); -- 小组表索引 CREATE INDEX idx_group_owner ON `group`(ownerId); CREATE INDEX idx_group_is_active ON `group`(isActive); CREATE INDEX idx_group_is_public ON `group`(isPublic); CREATE INDEX idx_group_created_at ON `group`(createdAt); -- 小组成员表索引 CREATE INDEX idx_member_group_user ON group_member(groupId, userId); CREATE INDEX idx_member_user ON group_member(userId); CREATE INDEX idx_member_is_active ON group_member(isActive); CREATE INDEX idx_member_role ON group_member(role); -- 预约表索引 CREATE INDEX idx_appointment_group ON appointment(groupId); CREATE INDEX idx_appointment_creator ON appointment(initiatorId); CREATE INDEX idx_appointment_date ON appointment(eventDate); CREATE INDEX idx_appointment_status ON appointment(status); CREATE INDEX idx_appointment_created_at ON appointment(createdAt); -- 预约参与者表索引 CREATE INDEX idx_participant_appointment ON appointment_participant(appointmentId); CREATE INDEX idx_participant_user ON appointment_participant(userId); -- 游戏表索引 CREATE INDEX idx_game_name ON game(name); CREATE INDEX idx_game_category ON game(category); -- 黑名单表索引 CREATE INDEX idx_blacklist_reporter ON blacklist(reporterId); CREATE INDEX idx_blacklist_reported ON blacklist(reportedUserId); CREATE INDEX idx_blacklist_status ON blacklist(status); -- 荣誉墙表索引 CREATE INDEX idx_honors_group ON honors(groupId); CREATE INDEX idx_honors_creator ON honors(creatorId); CREATE INDEX idx_honors_year ON honors(year); -- 积分表索引 CREATE INDEX idx_points_user ON points(userId); CREATE INDEX idx_points_type ON points(type); CREATE INDEX idx_points_created_at ON points(createdAt); -- 打赌表索引 CREATE INDEX idx_bets_creator ON bets(creatorId); CREATE INDEX idx_bets_status ON bets(status); CREATE INDEX idx_bets_deadline ON bets(deadline); ``` ### 数据库备份 ```bash # 手动备份 mysqldump -u root -p gamegroup > backup_$(date +%Y%m%d_%H%M%S).sql # 恢复备份 mysql -u root -p gamegroup < backup_20240101_120000.sql # 使用 Docker 备份 docker exec gamegroup-mysql-prod mysqldump -u root -p密码 gamegroup > backup.sql # 定时备份(添加到 crontab) 0 2 * * * mysqldump -u root -p密码 gamegroup > /backups/gamegroup_$(date +\%Y\%m\%d).sql ``` --- ## 性能优化建议 ### 1. 应用层优化 #### 启用 HTTP 压缩 已在 `main.ts` 中配置,确保 `.env` 中设置: ```env ENABLE_COMPRESSION=true ``` #### 缓存配置优化 根据实际流量调整缓存参数: ```env # 高流量场景 CACHE_TTL=600 # 10分钟 CACHE_MAX=5000 # 5000条缓存 # 中等流量 CACHE_TTL=300 # 5分钟 CACHE_MAX=1000 # 1000条缓存 # 低流量 CACHE_TTL=180 # 3分钟 CACHE_MAX=500 # 500条缓存 ``` #### 连接池优化 在 `database.config.ts` 中已配置: - 开发环境:10个连接 - 生产环境:20个连接 可根据服务器配置调整。 ### 2. 数据库优化 #### 查询缓存 生产环境已启用数据库查询缓存(1分钟)。 #### 慢查询日志 ```sql -- 启用慢查询日志 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2; SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log'; -- 查看慢查询统计 SHOW STATUS LIKE 'Slow_queries'; ``` #### 定期优化表 ```sql -- 优化所有表 OPTIMIZE TABLE user, `group`, group_member, appointment; -- 分析表 ANALYZE TABLE user, `group`, group_member; ``` ### 3. 服务器配置优化 #### Nginx 反向代理(推荐) ```nginx upstream backend { server localhost:3000; # 如果有多个实例,添加更多服务器 # server localhost:3001; # server localhost:3002; } server { listen 80; server_name your-domain.com; # 请求体大小限制 client_max_body_size 10M; # Gzip 压缩 gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 1000; location / { proxy_pass http://backend; 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_cache_bypass $http_upgrade; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # API 限流 location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://backend; } } # 限流配置(在 http 块中) limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; ``` --- ## 监控和维护 ### 1. 健康检查端点 ```bash # 应用健康检查 curl http://localhost:3000/health # 期望响应 {"status": "ok"} ``` ### 2. 日志管理 #### 查看应用日志 ```bash # Docker 环境 docker-compose -f docker-compose.prod.yml logs -f backend # PM2 环境 pm2 logs gamegroup-backend # 查看错误日志 pm2 logs gamegroup-backend --err # 查看输出日志 pm2 logs gamegroup-backend --out ``` #### 日志轮转配置 PM2 日志轮转: ```bash # 安装 PM2 日志轮转模块 pm2 install pm2-logrotate # 配置最大日志大小 pm2 set pm2-logrotate:max_size 10M # 配置保留天数 pm2 set pm2-logrotate:retain 7 # 配置压缩 pm2 set pm2-logrotate:compress true ``` ### 3. 性能监控 #### 内置监控 ```bash # PM2 监控 pm2 monit # 查看详细指标 pm2 show gamegroup-backend ``` #### 推荐监控工具 - **New Relic**: 应用性能监控 (APM) - **Datadog**: 全栈监控 - **Prometheus + Grafana**: 开源监控方案 - **ELK Stack**: 日志聚合和分析 ### 4. 数据库监控 ```sql -- 查看连接数 SHOW STATUS LIKE 'Threads_connected'; -- 查看最大连接数 SHOW VARIABLES LIKE 'max_connections'; -- 查看查询统计 SHOW STATUS LIKE 'Questions'; SHOW STATUS LIKE 'Queries'; -- 查看慢查询 SHOW STATUS LIKE 'Slow_queries'; -- 查看当前运行的查询 SHOW PROCESSLIST; ``` --- ## 常见问题排查 ### 1. 应用无法启动 #### 检查端口占用 ```bash # Windows netstat -ano | findstr :3000 # Linux/Mac lsof -i :3000 ``` #### 检查环境变量 ```bash # 确认环境变量已加载 echo $NODE_ENV # 检查配置文件 cat .env.production ``` #### 查看详细错误 ```bash # Docker docker-compose -f docker-compose.prod.yml logs backend # PM2 pm2 logs gamegroup-backend --lines 100 ``` ### 2. 数据库连接失败 #### 检查数据库服务 ```bash # 检查 MySQL 是否运行 # Windows sc query MySQL80 # Linux systemctl status mysql # Docker docker ps | grep mysql ``` #### 测试数据库连接 ```bash mysql -h localhost -u gamegroup -p -D gamegroup ``` #### 常见错误 - **ER_ACCESS_DENIED_ERROR**: 用户名或密码错误 - **ECONNREFUSED**: 数据库服务未启动或端口错误 - **ER_BAD_DB_ERROR**: 数据库不存在 ### 3. 内存占用过高 #### 查看内存使用 ```bash # PM2 pm2 show gamegroup-backend # Docker docker stats gamegroup-backend-prod ``` #### 解决方案 ```bash # PM2 设置内存限制(在 ecosystem.config.js 中) max_memory_restart: '500M' # 重启应用释放内存 pm2 restart gamegroup-backend ``` ### 4. 性能问题 #### 分析慢查询 ```sql -- 查看慢查询日志 SELECT * FROM mysql.slow_log; -- 使用 EXPLAIN 分析查询 EXPLAIN SELECT * FROM user WHERE username = 'test'; ``` #### 检查缓存命中率 查看应用日志,搜索 "Cache hit" 和 "Cache miss"。 #### 数据库优化 ```sql -- 检查表状态 SHOW TABLE STATUS LIKE 'user'; -- 优化表 OPTIMIZE TABLE user; -- 更新统计信息 ANALYZE TABLE user; ``` ### 5. Docker 相关问题 #### 容器无法启动 ```bash # 查看容器日志 docker logs gamegroup-backend-prod # 检查容器状态 docker inspect gamegroup-backend-prod # 重新构建 docker-compose -f docker-compose.prod.yml build --no-cache ``` #### 数据持久化问题 ```bash # 查看数据卷 docker volume ls # 检查数据卷 docker volume inspect gamegroup_mysql-data # 备份数据卷 docker run --rm -v gamegroup_mysql-data:/data -v $(pwd):/backup ubuntu tar czf /backup/mysql-backup.tar.gz /data ``` --- ## 安全建议 ### 1. 环境变量安全 - ✅ 不要将 `.env` 文件提交到 Git - ✅ 使用强密码(至少16位,包含大小写字母、数字、特殊字符) - ✅ 定期更换 JWT_SECRET - ✅ 限制 CORS_ORIGIN 为实际域名 ### 2. 数据库安全 - ✅ 不使用 root 用户连接 - ✅ 限制数据库用户权限(不给 DROP、ALTER 等危险权限) - ✅ 使用防火墙限制数据库端口访问 - ✅ 启用 SSL/TLS 连接 ### 3. 应用安全 - ✅ 定期更新依赖包:`npm audit fix` - ✅ 启用 HTTPS(使用 Let's Encrypt 免费证书) - ✅ 实施请求速率限制 - ✅ 设置 HTTP 安全头(Helmet 中间件) - ✅ 输入验证和 SQL 注入防护(已使用 TypeORM) ### 4. 网络安全 ```bash # 配置防火墙(Ubuntu/Debian) sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 22/tcp sudo ufw deny 3306/tcp # 拒绝外部访问数据库 sudo ufw enable # 仅允许特定 IP 访问数据库 sudo ufw allow from 服务器IP to any port 3306 ``` --- ## 升级和回滚 ### 应用升级 ```bash # 1. 拉取最新代码 git pull origin main # 2. 安装依赖 npm ci # 3. 运行测试 npm test # 4. 构建应用 npm run build:prod # 5. 备份数据库 mysqldump -u root -p gamegroup > backup_before_upgrade.sql # 6. 使用 PM2 重载(零停机) pm2 reload gamegroup-backend # 或使用 Docker docker-compose -f docker-compose.prod.yml up -d --build ``` ### 应用回滚 ```bash # 1. 切换到上一个版本 git checkout 上一个稳定版本的commit # 2. 重新构建和部署 npm ci npm run build:prod pm2 restart gamegroup-backend # 3. 如需回滚数据库 mysql -u root -p gamegroup < backup_before_upgrade.sql ``` --- ## 生产环境检查清单 部署前请确认以下项目: - [ ] 已设置强 JWT_SECRET - [ ] 已设置强数据库密码 - [ ] DB_SYNCHRONIZE 设置为 false - [ ] DB_LOGGING 设置为 false - [ ] CORS_ORIGIN 限制为实际域名 - [ ] 已创建数据库索引 - [ ] 已配置数据库备份 - [ ] 已设置日志轮转 - [ ] 已配置监控告警 - [ ] 已进行压力测试 - [ ] 已准备回滚方案 - [ ] 已配置 HTTPS - [ ] 已设置防火墙规则 - [ ] 已配置健康检查 - [ ] 已测试备份恢复流程 --- ## 技术支持 ### 文档参考 - **NestJS 官方文档**: https://docs.nestjs.com/ - **TypeORM 文档**: https://typeorm.io/ - **PM2 文档**: https://pm2.keymetrics.io/ - **Docker 文档**: https://docs.docker.com/ ### 问题反馈 如遇到部署问题,请提供: 1. 错误日志(完整堆栈跟踪) 2. 环境信息(Node.js、MySQL 版本) 3. 配置文件(隐藏敏感信息) 4. 复现步骤 --- **祝部署顺利!** 🚀