diff --git a/docs/部署指南.md b/docs/部署指南.md new file mode 100644 index 0000000..4c7a3a4 --- /dev/null +++ b/docs/部署指南.md @@ -0,0 +1,696 @@ +# 游戏平台服务器部署指南 + +本文档提供游戏平台服务器(Game Platform Server)的完整部署指南,包括环境准备、数据库配置、应用部署和运行维护等内容。 + +## 目录 +- [系统要求](#系统要求) +- [环境准备](#环境准备) +- [数据库配置](#数据库配置) +- [应用配置](#应用配置) +- [构建和部署](#构建和部署) +- [启动和验证](#启动和验证) +- [监控和维护](#监控和维护) +- [故障排除](#故障排除) +- [安全注意事项](#安全注意事项) + +## 系统要求 + +### 硬件要求 +- **CPU**: 2核心以上(推荐4核心) +- **内存**: 4GB以上(推荐8GB) +- **存储**: 20GB以上可用空间 +- **网络**: 稳定的网络连接 + +### 软件要求 +- **操作系统**: + - Linux(推荐 Ubuntu 20.04+ 或 CentOS 7+) + - macOS 10.15+ + - Windows 10+ +- **Java**: JDK 17 或更高版本 +- **Maven**: 3.9+ 版本 +- **MySQL**: 8.0+ 版本 +- **Git**: 用于代码拉取 + +## 环境准备 + +### 1. 安装 Java 17 + +#### Ubuntu/Debian +```bash +sudo apt update +sudo apt install openjdk-17-jdk +``` + +#### CentOS/RHEL +```bash +sudo yum install java-17-openjdk-devel +``` + +#### macOS +```bash +brew install openjdk@17 +``` + +验证安装: +```bash +java -version +javac -version +``` + +### 2. 安装 Maven + +#### Ubuntu/Debian +```bash +sudo apt install maven +``` + +#### CentOS/RHEL +```bash +sudo yum install maven +``` + +#### macOS +```bash +brew install maven +``` + +验证安装: +```bash +mvn -version +``` + +### 3. 安装 MySQL 8.0 + +#### Ubuntu/Debian +```bash +sudo apt update +sudo apt install mysql-server-8.0 +sudo mysql_secure_installation +``` + +#### CentOS/RHEL +```bash +sudo yum install mysql-server +sudo systemctl enable mysqld +sudo systemctl start mysqld +sudo mysql_secure_installation +``` + +#### macOS +```bash +brew install mysql +brew services start mysql +``` + +## 数据库配置 + +### 1. 创建数据库和用户 + +登录 MySQL: +```bash +sudo mysql -u root -p +``` + +创建数据库和用户: +```sql +-- 创建数据库 +CREATE DATABASE login_task_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; + +-- 创建用户(如果需要) +CREATE USER 'login_task_db'@'%' IDENTIFIED BY '3MaXfeWJ4d6cGMrL'; + +-- 授权 +GRANT ALL PRIVILEGES ON login_task_db.* TO 'login_task_db'@'%'; +FLUSH PRIVILEGES; + +-- 退出 +EXIT; +``` + +### 2. 初始化数据库表结构 + +```bash +# 切换到项目目录 +cd /path/to/game_server + +# 执行基础表结构 +mysql -u login_task_db -p login_task_db < src/main/resources/schema.sql + +# 执行迁移脚本(如果存在) +mysql -u login_task_db -p login_task_db < src/main/resources/db/migration/V20250915__create_device_status_transition.sql +mysql -u login_task_db -p login_task_db < src/main/resources/db/migration/V20250920__create_script_operation_log.sql + +# 如果有其他初始化SQL文件,也需要执行 +# mysql -u login_task_db -p login_task_db < docs/game.sql +``` + +### 3. 验证数据库连接 + +```bash +mysql -u login_task_db -p -h localhost login_task_db -e "SHOW TABLES;" +``` + +## 应用配置 + +### 1. 克隆项目代码 + +```bash +# 克隆代码仓库 +git clone game_server +cd game_server +``` + +### 2. 配置应用参数 + +复制并修改配置文件: +```bash +# 备份原配置 +cp src/main/resources/application.yml src/main/resources/application.yml.backup + +# 编辑配置文件 +vim src/main/resources/application.yml +``` + +### 3. 关键配置项说明 + +#### 数据库配置 +```yaml +spring: + datasource: + url: jdbc:mysql://localhost:3306/login_task_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&sessionVariables=innodb_lock_wait_timeout=30 + username: login_task_db + password: 3MaXfeWJ4d6cGMrL # 请修改为实际密码 + driver-class-name: com.mysql.cj.jdbc.Driver +``` + +#### 服务器配置 +```yaml +server: + port: 18080 # 可根据需要修改端口 +``` + +#### JWT 安全配置 +```yaml +security: + jwt: + secret: "your-super-long-secret-key-here" # 生产环境必须修改 + access-token-minutes: 1440 + refresh-token-days: 7 +``` + +#### 外部服务配置 +```yaml +script: + base-url: "http://36.138.184.60:12345" # 根据实际环境修改 + api-base-url: "http://36.138.184.60:1234" # 根据实际环境修改 + connect-timeout-ms: 3000 + read-timeout-ms: 5000 + +app: + base-url: "https://yourdomain.com" # 修改为实际域名 +``` + +### 4. 环境变量配置(推荐) + +为了安全起见,建议使用环境变量配置敏感信息: + +```bash +# 创建环境变量文件 +cat > .env << EOF +DB_HOST=localhost +DB_PORT=3306 +DB_NAME=login_task_db +DB_USERNAME=login_task_db +DB_PASSWORD=3MaXfeWJ4d6cGMrL +JWT_SECRET=your-super-long-secret-key-here +SERVER_PORT=18080 +SCRIPT_BASE_URL=http://36.138.184.60:12345 +SCRIPT_API_BASE_URL=http://36.138.184.60:1234 +APP_BASE_URL=https://yourdomain.com +EOF + +# 加载环境变量 +source .env +``` + +## 构建和部署 + +### 1. 构建应用 + +```bash +# 清理并编译 +mvn clean compile + +# 运行测试(可选) +mvn test + +# 打包应用 +mvn clean package -DskipTests +``` + +构建成功后,JAR文件位于 `target/server-0.0.1-SNAPSHOT.jar` + +### 2. 创建部署目录 + +```bash +# 创建部署目录 +sudo mkdir -p /opt/gameplatform +sudo chown $USER:$USER /opt/gameplatform + +# 复制文件 +cp target/server-0.0.1-SNAPSHOT.jar /opt/gameplatform/ +cp -r logs /opt/gameplatform/ 2>/dev/null || mkdir /opt/gameplatform/logs +cp .env /opt/gameplatform/ 2>/dev/null || true +``` + +### 3. 创建启动脚本 + +```bash +cat > /opt/gameplatform/start.sh << 'EOF' +#!/bin/bash + +# 设置工作目录 +cd /opt/gameplatform + +# 加载环境变量 +if [ -f .env ]; then + source .env +fi + +# 设置JVM参数 +JAVA_OPTS="-Xms1g -Xmx2g -server" +JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=prod" +JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8" +JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true" + +# 启动应用 +java $JAVA_OPTS -jar server-0.0.1-SNAPSHOT.jar > logs/console.log 2>&1 & + +# 保存进程ID +echo $! > app.pid + +echo "应用已启动,进程ID: $(cat app.pid)" +echo "日志文件: logs/console.log" +echo "应用端口: ${SERVER_PORT:-18080}" +EOF + +chmod +x /opt/gameplatform/start.sh +``` + +### 4. 创建停止脚本 + +```bash +cat > /opt/gameplatform/stop.sh << 'EOF' +#!/bin/bash + +cd /opt/gameplatform + +if [ -f app.pid ]; then + PID=$(cat app.pid) + if ps -p $PID > /dev/null; then + echo "正在停止应用 (PID: $PID)..." + kill -TERM $PID + + # 等待进程优雅退出 + for i in {1..30}; do + if ! ps -p $PID > /dev/null; then + echo "应用已成功停止" + rm -f app.pid + exit 0 + fi + sleep 1 + done + + # 强制终止 + echo "强制终止应用..." + kill -KILL $PID + rm -f app.pid + else + echo "应用未运行" + rm -f app.pid + fi +else + echo "未找到PID文件" +fi +EOF + +chmod +x /opt/gameplatform/stop.sh +``` + +### 5. 创建重启脚本 + +```bash +cat > /opt/gameplatform/restart.sh << 'EOF' +#!/bin/bash + +cd /opt/gameplatform + +echo "重启应用..." +./stop.sh +sleep 2 +./start.sh +EOF + +chmod +x /opt/gameplatform/restart.sh +``` + +## 启动和验证 + +### 1. 启动应用 + +```bash +cd /opt/gameplatform +./start.sh +``` + +### 2. 检查启动状态 + +```bash +# 检查进程 +ps aux | grep java + +# 检查端口 +netstat -tlnp | grep 18080 + +# 查看启动日志 +tail -f logs/console.log +``` + +### 3. 健康检查 + +```bash +# 基础健康检查 +curl http://localhost:18080/actuator/health + +# 预期返回 +{"status":"UP"} +``` + +### 4. API测试 + +```bash +# 测试登录接口(需要先在数据库中创建用户) +curl -X POST http://localhost:18080/api/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"admin7uqweh12"}' + +# 访问Swagger文档 +curl http://localhost:18080/swagger-ui.html +``` + +## 监控和维护 + +### 1. 创建系统服务(推荐) + +```bash +sudo tee /etc/systemd/system/gameplatform.service > /dev/null << 'EOF' +[Unit] +Description=Game Platform Server +After=network.target mysql.service + +[Service] +Type=forking +User=gameplatform +Group=gameplatform +WorkingDirectory=/opt/gameplatform +ExecStart=/opt/gameplatform/start.sh +ExecStop=/opt/gameplatform/stop.sh +ExecReload=/opt/gameplatform/restart.sh +PIDFile=/opt/gameplatform/app.pid +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +# 创建专用用户 +sudo useradd -r -s /bin/false gameplatform +sudo chown -R gameplatform:gameplatform /opt/gameplatform + +# 启用并启动服务 +sudo systemctl daemon-reload +sudo systemctl enable gameplatform +sudo systemctl start gameplatform +sudo systemctl status gameplatform +``` + +### 2. 日志轮转配置 + +```bash +sudo tee /etc/logrotate.d/gameplatform > /dev/null << 'EOF' +/opt/gameplatform/logs/*.log { + daily + missingok + rotate 30 + compress + notifempty + create 644 gameplatform gameplatform + postrotate + systemctl reload gameplatform 2>/dev/null || true + endscript +} +EOF +``` + +### 3. 监控脚本 + +```bash +cat > /opt/gameplatform/monitor.sh << 'EOF' +#!/bin/bash + +cd /opt/gameplatform + +check_process() { + if [ -f app.pid ]; then + PID=$(cat app.pid) + if ps -p $PID > /dev/null; then + echo "✓ 应用正在运行 (PID: $PID)" + return 0 + else + echo "✗ 应用未运行(PID文件存在但进程不存在)" + rm -f app.pid + return 1 + fi + else + echo "✗ 应用未运行(未找到PID文件)" + return 1 + fi +} + +check_port() { + PORT=${SERVER_PORT:-18080} + if netstat -tlnp 2>/dev/null | grep ":$PORT " > /dev/null; then + echo "✓ 端口 $PORT 正在监听" + return 0 + else + echo "✗ 端口 $PORT 未监听" + return 1 + fi +} + +check_health() { + PORT=${SERVER_PORT:-18080} + if curl -sf http://localhost:$PORT/actuator/health > /dev/null; then + echo "✓ 健康检查通过" + return 0 + else + echo "✗ 健康检查失败" + return 1 + fi +} + +echo "=== 游戏平台服务器状态检查 ===" +echo "时间: $(date)" +echo + +check_process && check_port && check_health + +echo +echo "最近的日志:" +tail -5 logs/console.log 2>/dev/null || echo "无法读取日志文件" +EOF + +chmod +x /opt/gameplatform/monitor.sh +``` + +## 故障排除 + +### 常见问题和解决方案 + +#### 1. 应用启动失败 + +**检查步骤:** +```bash +# 查看详细错误日志 +tail -100 /opt/gameplatform/logs/console.log + +# 检查Java版本 +java -version + +# 检查端口占用 +netstat -tlnp | grep 18080 +``` + +**常见原因:** +- Java版本不兼容(需要Java 17+) +- 端口被占用 +- 数据库连接失败 +- 配置文件错误 + +#### 2. 数据库连接问题 + +**检查步骤:** +```bash +# 测试数据库连接 +mysql -u login_task_db -p -h localhost login_task_db + +# 检查MySQL服务状态 +sudo systemctl status mysql +``` + +**解决方案:** +- 确认MySQL服务正在运行 +- 检查用户名密码是否正确 +- 确认数据库名称是否存在 +- 检查防火墙设置 + +#### 3. 内存不足 + +**症状:** +- 应用启动缓慢或失败 +- 频繁的垃圾回收 + +**解决方案:** +```bash +# 调整JVM内存参数(修改start.sh) +JAVA_OPTS="-Xms512m -Xmx1g -server" +``` + +#### 4. 权限问题 + +```bash +# 修复文件权限 +sudo chown -R gameplatform:gameplatform /opt/gameplatform +sudo chmod +x /opt/gameplatform/*.sh +``` + +### 日志查看命令 + +```bash +# 查看应用日志 +tail -f /opt/gameplatform/logs/console.log + +# 查看系统服务日志 +sudo journalctl -u gameplatform -f + +# 查看错误日志 +grep -i error /opt/gameplatform/logs/console.log + +# 查看最近100行日志 +tail -100 /opt/gameplatform/logs/console.log +``` + +## 安全注意事项 + +### 1. 修改默认配置 + +**必须修改的配置项:** +- JWT密钥:修改 `security.jwt.secret` +- 数据库密码:使用强密码 +- 默认用户密码:修改admin账户密码 + +### 2. 网络安全 + +```bash +# 配置防火墙(示例:Ubuntu UFW) +sudo ufw allow 18080/tcp +sudo ufw allow 22/tcp +sudo ufw enable + +# 限制数据库访问 +sudo ufw allow from 127.0.0.1 to any port 3306 +``` + +### 3. 文件权限 + +```bash +# 设置适当的文件权限 +chmod 600 /opt/gameplatform/.env +chmod 750 /opt/gameplatform +chmod 644 /opt/gameplatform/*.jar +``` + +### 4. SSL/TLS配置 + +生产环境建议配置HTTPS: + +```yaml +server: + port: 443 + ssl: + enabled: true + key-store: classpath:keystore.p12 + key-store-password: your-keystore-password + key-store-type: PKCS12 +``` + +## 更新和维护 + +### 应用更新流程 + +```bash +# 1. 备份当前版本 +cp /opt/gameplatform/server-0.0.1-SNAPSHOT.jar /opt/gameplatform/server-backup-$(date +%Y%m%d).jar + +# 2. 停止应用 +cd /opt/gameplatform +./stop.sh + +# 3. 更新代码和构建 +cd /path/to/source +git pull +mvn clean package -DskipTests + +# 4. 替换JAR文件 +cp target/server-0.0.1-SNAPSHOT.jar /opt/gameplatform/ + +# 5. 启动应用 +cd /opt/gameplatform +./start.sh + +# 6. 验证更新 +./monitor.sh +``` + +### 数据库备份 + +```bash +# 创建备份脚本 +cat > /opt/gameplatform/backup_db.sh << 'EOF' +#!/bin/bash +BACKUP_DIR="/opt/gameplatform/backups" +DATE=$(date +%Y%m%d_%H%M%S) + +mkdir -p $BACKUP_DIR + +mysqldump -u login_task_db -p3MaXfeWJ4d6cGMrL login_task_db > $BACKUP_DIR/login_task_db_$DATE.sql + +# 压缩备份文件 +gzip $BACKUP_DIR/login_task_db_$DATE.sql + +# 删除7天前的备份 +find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete + +echo "数据库备份完成: $BACKUP_DIR/login_task_db_$DATE.sql.gz" +EOF + +chmod +x /opt/gameplatform/backup_db.sh + +# 设置定时备份(每天凌晨2点) +echo "0 2 * * * /opt/gameplatform/backup_db.sh" | sudo crontab - +``` + +--- + +本文档提供了游戏平台服务器的完整部署指南。如有问题,请参考项目的其他文档或联系开发团队。 diff --git a/src/main/java/com/gameplatform/server/service/device/DeviceStatusCheckService.java b/src/main/java/com/gameplatform/server/service/device/DeviceStatusCheckService.java index c8e2e71..2270f8b 100644 --- a/src/main/java/com/gameplatform/server/service/device/DeviceStatusCheckService.java +++ b/src/main/java/com/gameplatform/server/service/device/DeviceStatusCheckService.java @@ -74,13 +74,13 @@ public class DeviceStatusCheckService { // 3. 如果设备空闲,通过完成检测服务进行判定(含缓冲与二次确认)。 // 若未能直接判定完成,则执行兜底:将该设备上 LOGGED_IN 的任务批量置为 COMPLETED,并写入原因。 if (statusInfo.isIdle()) { - String source = "TIMER_TASK"; + String source = reason != null ? reason : "UNKNOWN_REASON"; com.gameplatform.server.util.AuditLogger.debug("IdleDetected: device={}, source={}, status={}, points={}", machineId, source, statusInfo.getStatus(), statusInfo.getPoints()); // 调用完成检测服务(包含登录缓冲与二次确认) boolean done = completionDetectionService.detectGameCompletion(machineId, statusInfo.getStatus(), source); if (!done) { // 兜底完成:当设备空闲,直接将 LOGGED_IN 任务置为完成 - String completionReason = "状态:已完成(空闲兜底)"; + String completionReason = String.format("状态:已完成(空闲兜底,触发原因:%s)", reason != null ? reason : "checkDeviceStatusAndUpdateTasks 未知"); Integer points = statusInfo.getPoints(); try { int affected = linkTaskMapper.completeLoggedInTasksByMachine(machineId, completionReason, points); diff --git a/src/main/java/com/gameplatform/server/task/DeviceStatusCheckTask.java b/src/main/java/com/gameplatform/server/task/DeviceStatusCheckTask.java index 07fb092..e58a251 100644 --- a/src/main/java/com/gameplatform/server/task/DeviceStatusCheckTask.java +++ b/src/main/java/com/gameplatform/server/task/DeviceStatusCheckTask.java @@ -30,7 +30,7 @@ public class DeviceStatusCheckTask { /** * 每分钟检查一次空闲设备,并更新相关链接任务状态 */ - @Scheduled(fixedRate = 60000) // 每60秒执行一次 + // @Scheduled(fixedRate = 60000) // 每60秒执行一次 public void checkIdleDevicesAndUpdateTasks() { log.debug("开始定时检查空闲设备");