diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..37ec968 --- /dev/null +++ b/.env.example @@ -0,0 +1,69 @@ +# 应用配置 +NODE_ENV=production +PORT=3000 + +# Kafka配置 +KAFKA_BROKERS=localhost:9092 +KAFKA_TOPIC=blwlog4Nodejs-rcu-heartbeat-topic +KAFKA_TOPICS= +KAFKA_GROUP_ID=bls-heartbeat-consumer +KAFKA_CLIENT_ID=bls-heartbeat +KAFKA_CONSUMER_INSTANCES=6 +KAFKA_AUTO_COMMIT=true +KAFKA_AUTO_COMMIT_INTERVAL_MS=5000 +KAFKA_RETRY_ATTEMPTS=0 +KAFKA_RETRY_DELAY=1000 +KAFKA_MAX_IN_FLIGHT_MESSAGES=200 + +# Kafka SASL配置(如果需要) +KAFKA_SASL_ENABLED=false +KAFKA_SASL_MECHANISM=plain +KAFKA_SASL_USERNAME= +KAFKA_SASL_PASSWORD= + +# Kafka SSL配置(如果需要) +KAFKA_SSL_ENABLED=false + +# PostgreSQL配置 +POSTGRES_HOST=127.0.0.1 +POSTGRES_PORT=5432 +POSTGRES_DATABASE=log_platform +POSTGRES_USER=log_admin +POSTGRES_PASSWORD=your_password +POSTGRES_IDLE_TIMEOUT_MS=30000 + +# PostgreSQL环境变量(兼容性) +PGHOST= +PGPORT= +PGTARGETDB= +PGUSER= +PGPASSWORD= + +# 数据库重试配置 +DB_RETRY_ATTEMPTS=3 +DB_RETRY_DELAY=1000 +DB_PARTITION_MAINTENANCE_ENABLED=true +DB_PARTITION_FUTURE_DAYS=30 +DB_PARTITION_INTERVAL_HOURS=6 + +# Redis配置 +REDIS_ENABLED=true +REDIS_HOST=10.8.8.109 +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_DB=15 +REDIS_URL= +REDIS_CONNECT_TIMEOUT_MS=5000 +REDIS_PROJECT_NAME=BLS主机心跳日志 +REDIS_HEARTBEAT_INTERVAL_MS=3000 +REDIS_HEARTBEAT_TTL_SECONDS=30 +REDIS_API_BASE_URL=http://127.0.0.1:3000 +REDIS_CONSOLE_MAX_LEN= + +# 处理器配置 +PROCESSOR_BATCH_SIZE=100 +PROCESSOR_BATCH_TIMEOUT=5000 + +# 日志配置 +LOG_LEVEL=info +LOG_FORMAT=json \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1f3292e..2ea494c 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ coverage/ # 临时文件 *.tmp *.temp -.cache/ \ No newline at end of file +.cache/ +release diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..2de5d2c --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,292 @@ +# BLS心跳接收端发布流程 + +## 环境要求 + +- Windows Server系统 +- Node.js 环境(已安装) +- PM2 进程管理器(已安装) +- PostgreSQL 数据库 +- Kafka 消息队列 +- Redis(可选) + +## 发布流程 + +### 1. 准备发布包 + +在开发机器上执行以下命令: + +```bash +# 安装依赖 +npm install + +# 构建项目 +npm run build + +# 创建发布包(包含必要的文件) +# 方法1:手动复制文件 +# 复制以下文件到发布目录: +# - dist/ (构建后的文件) +# - package.json +# - package-lock.json +# - src/config/config.example.js +# - scripts/db/ (数据库脚本) + +# 方法2:使用压缩包 +# 创建包含上述文件的压缩包 +``` + +### 2. 上传到目标服务器 + +将发布包上传到目标服务器的指定目录,例如:`C:\BLS_Heartbeat_Server` + +### 3. 在目标服务器上部署 + +```bash +# 进入项目目录 +cd C:\BLS_Heartbeat_Server + +# 安装生产依赖 +npm install --production + +# 创建环境变量文件 +# 复制配置示例并修改 +copy src\config\config.example.js src\config\config.js + +# 或者创建 .env 文件(推荐) +# 复制 .env.example 并修改为 .env +copy .env.example .env + +# 编辑配置文件,设置实际的数据库、Kafka、Redis连接信息 +notepad .env +``` + +### 4. 配置环境变量 + +编辑 `.env` 文件,设置以下关键配置: + +```env +# 应用配置 +NODE_ENV=production +PORT=3000 + +# Kafka配置 +KAFKA_BROKERS=localhost:9092 +KAFKA_TOPIC=blwlog4Nodejs-rcu-heartbeat-topic +KAFKA_GROUP_ID=bls-heartbeat-consumer +KAFKA_CONSUMER_INSTANCES=6 + +# PostgreSQL配置 +POSTGRES_HOST=127.0.0.1 +POSTGRES_PORT=5432 +POSTGRES_DATABASE=log_platform +POSTGRES_USER=log_admin +POSTGRES_PASSWORD=your_password + +# Redis配置(可选) +REDIS_ENABLED=true +REDIS_HOST=10.8.8.109 +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_DB=15 + +# 日志配置 +LOG_LEVEL=info +LOG_FORMAT=json +``` + +### 5. 初始化数据库 + +```bash +# 运行数据库初始化脚本 +npm run db:apply +``` + +### 6. 使用PM2启动服务 + +```bash +# 使用PM2启动服务 +pm2 start ecosystem.config.js + +# 查看服务状态 +pm2 status + +# 查看日志 +pm2 logs web-bls-heartbeat-server + +# 查看详细信息 +pm2 show web-bls-heartbeat-server +``` + +### 7. 设置PM2开机自启 + +```bash +# 保存当前PM2进程列表 +pm2 save + +# 设置开机自启(Windows需要管理员权限) +pm2 startup +``` + +## PM2配置说明 + +项目提供了 `ecosystem.config.js` 配置文件,包含以下配置: + +- 应用名称:`web-bls-heartbeat-server` +- 运行模式:`cluster`(集群模式) +- 实例数量:根据CPU核心数自动设置 +- 日志文件:`logs/` 目录下 +- 环境变量:从 `.env` 文件加载 + +## 监控和维护 + +### 查看服务状态 + +```bash +# 查看所有服务状态 +pm2 status + +# 查看特定服务状态 +pm2 show web-bls-heartbeat-server + +# 实时监控 +pm2 monit +``` + +### 日志管理 + +```bash +# 查看实时日志 +pm2 logs web-bls-heartbeat-server + +# 查看错误日志 +pm2 logs web-bls-heartbeat-server --err + +# 清空日志 +pm2 flush + +# 日志轮转(需要安装pm2-logrotate) +pm2 install pm2-logrotate +``` + +### 服务重启 + +```bash +# 重启服务 +pm2 restart web-bls-heartbeat-server + +# 优雅重启(集群模式) +pm2 reload web-bls-heartbeat-server + +# 停止服务 +pm2 stop web-bLS-heartbeat-server + +# 删除服务 +pm2 delete web-bls-heartbeat-server +``` + +### 更新部署 + +```bash +# 停止服务 +pm2 stop web-bls-heartbeat-server + +# 备份当前版本 +xcopy /E /I /Y C:\BLS_Heartbeat_Server C:\BLS_Heartbeat_Server_backup + +# 上传新版本文件 + +# 安装依赖(如果有更新) +npm install --production + +# 重启服务 +pm2 start ecosystem.config.js + +# 验证服务状态 +pm2 status +pm2 logs web-bls-heartbeat-server +``` + +## 故障排查 + +### 服务无法启动 + +1. 检查Node.js版本:`node --version` +2. 检查PM2状态:`pm2 list` +3. 查看错误日志:`pm2 logs web-bls-heartbeat-server --err` +4. 检查配置文件:确认 `.env` 文件配置正确 +5. 检查网络连接:确认Kafka、PostgreSQL、Redis服务可访问 + +### 数据库连接失败 + +1. 检查PostgreSQL服务状态 +2. 验证数据库连接信息 +3. 检查防火墙设置 +4. 确认数据库用户权限 + +### Kafka连接失败 + +1. 检查Kafka服务状态 +2. 验证Kafka地址和端口 +3. 检查主题是否存在 +4. 确认消费者组配置 + +### Redis连接失败 + +1. 检查Redis服务状态 +2. 验证Redis连接信息 +3. 如果不需要Redis,设置 `REDIS_ENABLED=false` + +## 性能优化 + +### 调整消费者实例数 + +在 `.env` 文件中修改: + +```env +KAFKA_CONSUMER_INSTANCES=8 +``` + +### 调整批量处理参数 + +```env +PROCESSOR_BATCH_SIZE=200 +PROCESSOR_BATCH_TIMEOUT=3000 +``` + +### 调整数据库连接池 + +```env +DB_MAX_CONNECTIONS=10 +DB_IDLE_TIMEOUT_MS=30000 +``` + +## 安全建议 + +1. 不要在代码中硬编码密码,使用环境变量 +2. 限制数据库和Redis的访问IP +3. 定期更新依赖包:`npm audit fix` +4. 配置防火墙规则,限制不必要的端口访问 +5. 定期备份配置文件和数据库 + +## 备份策略 + +### 配置文件备份 + +```bash +# 备份环境配置 +copy .env .env.backup + +# 备份PM2配置 +pm2 save +``` + +### 数据库备份 + +```bash +# 使用pg_dump备份数据库 +pg_dump -h localhost -U log_admin -d log_platform > backup.sql +``` + +## 联系支持 + +如有问题,请查看项目文档或联系技术支持团队。 \ No newline at end of file diff --git a/docs/package-guide.md b/docs/package-guide.md new file mode 100644 index 0000000..24436fc --- /dev/null +++ b/docs/package-guide.md @@ -0,0 +1,157 @@ +# 发布包使用指南 + +## 发布包位置 + +发布包已生成在项目根目录下的 `release` 文件夹中。 + +## 发布包内容 + +``` +release/ +├── dist/ # 构建后的应用程序文件 +│ └── index.es.js # 主程序文件 +├── scripts/ # 部署脚本 +│ ├── deploy.bat # 首次部署脚本 +│ └── update.bat # 更新部署脚本 +├── src/ +│ └── config/ +│ └── config.example.js # 配置文件示例 +├── .env.example # 环境变量配置示例 +├── ecosystem.config.js # PM2进程管理配置 +├── package.json # 项目依赖配置 +├── package-lock.json # 依赖锁定文件 +└── README.txt # 快速使用说明 +``` + +## 部署步骤 + +### 1. 复制发布包 + +将整个 `release` 文件夹复制到目标服务器的指定目录,例如: +- `C:\BLS_Heartbeat_Server` + +### 2. 在目标服务器上部署 + +打开命令提示符(CMD)或PowerShell,进入项目目录: + +```cmd +cd C:\BLS_Heartbeat_Server +``` + +### 3. 运行部署脚本 + +```cmd +scripts\deploy.bat +``` + +部署脚本会自动完成以下操作: +- 检查Node.js和PM2环境 +- 安装项目依赖 +- 创建日志目录 +- 初始化数据库 +- 启动服务 + +### 4. 配置环境变量 + +首次运行后,需要编辑 `.env` 文件,设置实际的配置参数: + +```cmd +notepad .env +``` + +关键配置项: +- `KAFKA_BROKERS`: Kafka服务器地址 +- `KAFKA_TOPIC`: Kafka主题名称 +- `POSTGRES_HOST`: PostgreSQL服务器地址 +- `POSTGRES_DATABASE`: 数据库名称 +- `POSTGRES_USER`: 数据库用户名 +- `POSTGRES_PASSWORD`: 数据库密码 +- `REDIS_HOST`: Redis服务器地址(可选) + +### 5. 重启服务 + +配置完成后,重启服务使配置生效: + +```cmd +pm2 restart web-bls-heartbeat-server +``` + +## 更新部署 + +当有新版本时,可以运行更新脚本: + +```cmd +scripts\update.bat +``` + +更新脚本会自动完成以下操作: +- 停止当前服务 +- 备份当前版本 +- 更新依赖 +- 更新数据库 +- 重启服务 + +## 常用PM2命令 + +```cmd +# 查看服务状态 +pm2 status + +# 查看实时日志 +pm2 logs web-bls-heartbeat-server + +# 查看错误日志 +pm2 logs web-bls-heartbeat-server --err + +# 重启服务 +pm2 restart web-bls-heartbeat-server + +# 停止服务 +pm2 stop web-bls-heartbeat-server + +# 启动服务 +pm2 start ecosystem.config.js + +# 实时监控 +pm2 monit + +# 查看服务详情 +pm2 show web-bls-heartbeat-server + +# 清空日志 +pm2 flush +``` + +## 故障排查 + +### 服务无法启动 + +1. 检查Node.js版本:`node --version` +2. 检查PM2状态:`pm2 list` +3. 查看错误日志:`pm2 logs web-bls-heartbeat-server --err` +4. 检查配置文件:确认 `.env` 文件配置正确 + +### 数据库连接失败 + +1. 检查PostgreSQL服务是否运行 +2. 验证数据库连接信息 +3. 检查防火墙设置 +4. 确认数据库用户权限 + +### Kafka连接失败 + +1. 检查Kafka服务是否运行 +2. 验证Kafka地址和端口 +3. 检查主题是否存在 + +## 注意事项 + +1. 首次部署需要配置 `.env` 文件 +2. 确保目标服务器已安装Node.js和PM2 +3. 确保PostgreSQL、Kafka、Redis服务可访问 +4. 建议定期备份数据库和配置文件 +5. 生产环境建议设置PM2开机自启 + +## 技术支持 + +如有问题,请参考详细部署文档:`docs/deployment.md` \ No newline at end of file diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs new file mode 100644 index 0000000..5e50f88 --- /dev/null +++ b/ecosystem.config.cjs @@ -0,0 +1,31 @@ +module.exports = { + apps: [{ + name: 'bls-heartbeat', + script: 'dist/index.es.js', + instances: 1, + exec_mode: 'fork', + autorestart: true, + watch: false, + max_memory_restart: '1G', + env: { + NODE_ENV: 'production', + PORT: 3000 + }, + env_development: { + NODE_ENV: 'development', + PORT: 3000 + }, + error_file: './logs/error.log', + out_file: './logs/out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true, + time: true, + min_uptime: '10s', + max_restarts: 10, + restart_delay: 4000, + kill_timeout: 5000, + listen_timeout: 10000, + wait_ready: true, + shutdown_with_message: true + }] +}; \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..98f925f --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,31 @@ +module.exports = { + apps: [{ + name: 'bls-heartbeat-server', + script: 'dist/index.es.js', + instances: 'max', + exec_mode: 'cluster', + autorestart: true, + watch: false, + max_memory_restart: '1G', + env: { + NODE_ENV: 'production', + PORT: 3000 + }, + env_development: { + NODE_ENV: 'development', + PORT: 3000 + }, + error_file: './logs/error.log', + out_file: './logs/out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true, + time: true, + min_uptime: '10s', + max_restarts: 10, + restart_delay: 4000, + kill_timeout: 5000, + listen_timeout: 10000, + wait_ready: true, + shutdown_with_message: true + }] +}; \ No newline at end of file diff --git a/scripts/check-env.js b/scripts/check-env.js new file mode 100644 index 0000000..d3ddb61 --- /dev/null +++ b/scripts/check-env.js @@ -0,0 +1,115 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import kafka from 'kafka-node'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +console.log('--- 环境检查脚本开始 ---'); +console.log('当前时间:', new Date().toISOString()); +console.log('当前目录 (cwd):', process.cwd()); +console.log('脚本目录:', __dirname); + +// 1. 检查 .env 文件 +const pathsToCheck = [ + path.resolve(process.cwd(), '.env'), + path.resolve(__dirname, '../.env'), + path.resolve(__dirname, '../../.env') +]; +let envPath = null; +for (const p of pathsToCheck) { + if (fs.existsSync(p)) { + envPath = p; + break; + } +} + +if (envPath) { + console.log('✅ 找到 .env 文件:', envPath); + try { + const content = fs.readFileSync(envPath, 'utf8'); + const lines = content.split(/\r?\n/); + lines.forEach(line => { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) return; + const idx = trimmed.indexOf('='); + if (idx <= 0) return; + const key = trimmed.slice(0, idx).trim(); + let val = trimmed.slice(idx + 1).trim(); + if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) { + val = val.slice(1, -1); + } + envConfig[key] = val; + }); + console.log('已加载环境变量:', Object.keys(envConfig).filter(k => k.startsWith('KAFKA') || k.startsWith('PG') || k.startsWith('REDIS'))); + } catch (e) { + console.error('❌ 读取 .env 失败:', e.message); + } +} else { + console.warn('⚠️ .env 文件不存在! 将使用系统环境变量或默认值'); +} + +// 2. 确定 Kafka 配置 +const brokers = envConfig.KAFKA_BROKERS || process.env.KAFKA_BROKERS || 'localhost:9092'; +const topic = envConfig.KAFKA_TOPIC || process.env.KAFKA_TOPIC || 'blwlog4Nodejs-rcu-heartbeat-topic'; + +console.log('\n--- Kafka 连接配置 ---'); +console.log('Brokers:', brokers); +console.log('Topic:', topic); + +// 3. 测试连接 +console.log('\n--- 开始连接测试 ---'); +try { + const client = new kafka.KafkaClient({ + kafkaHost: brokers, + connectTimeout: 5000, + requestTimeout: 5000 + }); + + client.on('ready', () => { + console.log('✅ Kafka Client 连接成功 (Ready)'); + + console.log('正在加载 Topic Metadata...'); + client.loadMetadataForTopics([topic], (err, results) => { + if (err) { + console.error('❌ 获取 Metadata 失败:', err); + client.close(); + process.exit(1); + } + + console.log('✅ Metadata 获取成功'); + // console.log(JSON.stringify(results, null, 2)); + + const metadata = results[1].metadata; + if (metadata[topic]) { + console.log(`✅ Topic [${topic}] 存在,分区信息:`); + const partitions = metadata[topic]; + Object.keys(partitions).forEach(p => { + console.log(` - Partition ${p}: Leader ${partitions[p].leader}, Replicas ${partitions[p].replicas}`); + }); + } else { + console.warn(`⚠️ Topic [${topic}] 在 Metadata 中未找到 (可能自动创建中)`); + } + + client.close(() => { + console.log('\n测试完成: 网络连接正常'); + process.exit(0); + }); + }); + }); + + client.on('error', (err) => { + console.error('❌ Kafka 连接错误:', err); + // 不立即退出,等待超时或其他错误 + }); + + // 10秒超时兜底 + setTimeout(() => { + console.error('❌ 测试超时 (10秒) - 可能是防火墙或网络不通'); + process.exit(1); + }, 10000); + +} catch (e) { + console.error('❌ 初始化 Kafka Client 异常:', e); +} diff --git a/scripts/deploy.bat b/scripts/deploy.bat new file mode 100644 index 0000000..28485b5 --- /dev/null +++ b/scripts/deploy.bat @@ -0,0 +1,132 @@ +@echo off +chcp 65001 >nul +echo ======================================== +echo BLS心跳接收端部署脚本 +echo ======================================== + +setlocal enabledelayedexpansion + +:: 检查Node.js是否安装 +echo [1/7] 检查Node.js环境... +node --version >nul 2>&1 +if errorlevel 1 ( + echo [错误] 未检测到Node.js,请先安装Node.js + pause + exit /b 1 +) +echo [成功] Node.js版本: +node --version + +:: 检查PM2是否安装 +echo [2/7] 检查PM2环境... +pm2 --version >nul 2>&1 +if errorlevel 1 ( + echo [警告] 未检测到PM2,正在安装PM2... + call npm install -g pm2 + if errorlevel 1 ( + echo [错误] PM2安装失败 + pause + exit /b 1 + ) +) +echo [成功] PM2版本: +pm2 --version + +:: 检查.env文件 +echo [3/7] 检查环境配置文件... +if not exist ".env" ( + if exist ".env.example" ( + echo [信息] 创建.env文件... + copy .env.example .env >nul + echo [警告] 请编辑.env文件,设置正确的配置参数 + echo [提示] 使用记事本打开: notepad .env + pause + ) else ( + echo [错误] 未找到.env.example文件 + pause + exit /b 1 + ) +) else ( + echo [成功] 环境配置文件已存在 +) + +:: 安装依赖 +echo [4/7] 安装项目依赖... +if not exist "node_modules" ( + call npm install --production + if errorlevel 1 ( + echo [错误] 依赖安装失败 + pause + exit /b 1 + ) +) else ( + echo [信息] 依赖已存在,跳过安装 +) + +:: 创建日志目录 +echo [5/7] 创建日志目录... +if not exist "logs" ( + mkdir logs + echo [成功] 日志目录创建成功 +) else ( + echo [信息] 日志目录已存在 +) + +:: 检查构建文件 +echo [6/7] 检查构建文件... +if not exist "dist\index.es.js" ( + echo [警告] 未找到构建文件,请先运行 npm run build + echo [提示] 如果这是首次部署,请确保已上传dist目录 + pause + exit /b 1 +) +echo [成功] 构建文件检查通过 + +:: 初始化数据库 +echo [7/7] 初始化数据库... +echo [信息] 运行数据库初始化脚本... +call npm run db:apply +if errorlevel 1 ( + echo [警告] 数据库初始化失败,请检查数据库连接配置 + echo [提示] 可以稍后手动运行: npm run db:apply +) else ( + echo [成功] 数据库初始化完成 +) + +:: 使用PM2启动服务 +echo ======================================== +echo 启动服务 +echo ======================================== +pm2 start ecosystem.config.cjs +if errorlevel 1 ( + echo [错误] 服务启动失败 + pause + exit /b 1 +) + +:: 设置开机自启 +echo ======================================== +echo 设置开机自启 +echo ======================================== +pm2 save +pm2 startup +echo [提示] 请按照提示完成开机自启设置 + +:: 显示服务状态 +echo ======================================== +echo 服务状态 +echo ======================================== +pm2 status + +echo ======================================== +echo 部署完成! +echo ======================================== +echo. +echo 常用命令: +echo 查看状态: pm2 status +echo 查看日志: pm2 logs web-bls-heartbeat-server +echo 重启服务: pm2 restart web-bls-heartbeat-server +echo 停止服务: pm2 stop web-bls-heartbeat-server +echo 实时监控: pm2 monit +echo. +pause \ No newline at end of file diff --git a/scripts/package.bat b/scripts/package.bat new file mode 100644 index 0000000..fa61309 --- /dev/null +++ b/scripts/package.bat @@ -0,0 +1,95 @@ +@echo off +chcp 65001 >nul +echo ======================================== +echo BLS心跳接收端打包脚本 +echo ======================================== + +setlocal enabledelayedexpansion + +:: 设置发布目录 +set RELEASE_DIR=release +set VERSION=1.0.0 +set PACKAGE_NAME=web-bls-heartbeat-server-v%VERSION% + +echo [1/6] 清理旧的发布目录... +if exist "%RELEASE_DIR%" ( + rmdir /s /q "%RELEASE_DIR%" +) +mkdir "%RELEASE_DIR%" + +echo [2/6] 复制构建文件... +if exist "dist" ( + xcopy /E /I /Y dist "%RELEASE_DIR%\dist" >nul + echo [成功] 构建文件已复制 +) else ( + echo [错误] 未找到dist目录,请先运行 npm run build + pause + exit /b 1 +) + +echo [3/6] 复制配置文件... +copy package.json "%RELEASE_DIR%\" >nul +copy package-lock.json "%RELEASE_DIR%\" >nul +copy ecosystem.config.cjs "%RELEASE_DIR%\" >nul +copy .env.example "%RELEASE_DIR%\" >nul +echo [成功] 配置文件已复制 + +echo [4/6] 复制脚本文件... +if not exist "%RELEASE_DIR%\scripts" ( + mkdir "%RELEASE_DIR%\scripts" +) +copy scripts\deploy.bat "%RELEASE_DIR%\scripts\" >nul +copy scripts\update.bat "%RELEASE_DIR%\scripts\" >nul +copy scripts\check-env.js "%RELEASE_DIR%\scripts\" >nul +echo [成功] 脚本文件已复制 + +echo [5/6] 复制配置示例... +if not exist "%RELEASE_DIR%\src\config" ( + mkdir "%RELEASE_DIR%\src\config" +) +copy src\config\config.example.js "%RELEASE_DIR%\src\config\" >nul +echo [成功] 配置示例已复制 + +echo [6/6] 创建说明文件... +echo # BLS心跳接收端发布包 > "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo 版本: %VERSION% >> "%RELEASE_DIR%\README.txt" +echo 发布日期: %date% %time% >> "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo ## 快速部署指南 >> "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo 1. 将整个release文件夹复制到目标服务器 >> "%RELEASE_DIR%\README.txt" +echo 2. 进入项目目录: cd C:\BLS_Heartbeat_Server >> "%RELEASE_DIR%\README.txt" +echo 3. 运行部署脚本: scripts\deploy.bat >> "%RELEASE_DIR%\README.txt" +echo 4. 配置环境变量: 编辑.env文件 >> "%RELEASE_DIR%\README.txt" +echo 5. 服务将自动启动 >> "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo ## 文件说明 >> "%RELEASE_DIR%\README.txt" +echo - dist/: 构建后的应用程序文件 >> "%RELEASE_DIR%\README.txt" +echo - package.json: 项目依赖配置 >> "%RELEASE_DIR%\README.txt" +echo - ecosystem.config.js: PM2进程管理配置 >> "%RELEASE_DIR%\README.txt" +echo - .env.example: 环境变量配置示例 >> "%RELEASE_DIR%\README.txt" +echo - scripts/: 部署和更新脚本 >> "%RELEASE_DIR%\README.txt" +echo - src/config/config.example.js: 配置文件示例 >> "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo ## 常用命令 >> "%RELEASE_DIR%\README.txt" +echo - 首次部署: scripts\deploy.bat >> "%RELEASE_DIR%\README.txt" +echo - 更新部署: scripts\update.bat >> "%RELEASE_DIR%\README.txt" +echo - 查看状态: pm2 status >> "%RELEASE_DIR%\README.txt" +echo - 查看日志: pm2 logs web-bls-heartbeat-server >> "%RELEASE_DIR%\README.txt" +echo - 重启服务: pm2 restart web-bls-heartbeat-server >> "%RELEASE_DIR%\README.txt" +echo. >> "%RELEASE_DIR%\README.txt" +echo 详细文档请参考 docs/deployment.md >> "%RELEASE_DIR%\README.txt" +echo [成功] 说明文件已创建 + +echo ======================================== +echo 打包完成! +echo ======================================== +echo. +echo 发布目录: %RELEASE_DIR% +echo 发布包内容: +dir /b "%RELEASE_DIR%" +echo. +echo 复制整个 %RELEASE_DIR% 文件夹到目标服务器即可 +echo. +pause \ No newline at end of file diff --git a/scripts/update.bat b/scripts/update.bat new file mode 100644 index 0000000..13f30a1 --- /dev/null +++ b/scripts/update.bat @@ -0,0 +1,91 @@ +@echo off +chcp 65001 >nul +echo ======================================== +echo BLS心跳接收端更新脚本 +echo ======================================== + +setlocal enabledelayedexpansion + +:: 检查服务是否运行 +echo [1/6] 检查服务状态... +pm2 describe web-bls-heartbeat-server >nul 2>&1 +if errorlevel 1 ( + echo [警告] 服务未运行,跳过停止步骤 +) else ( + echo [信息] 停止服务... + pm2 stop web-bls-heartbeat-server + if errorlevel 1 ( + echo [错误] 服务停止失败 + pause + exit /b 1 + ) +) + +:: 备份当前版本 +echo [2/6] 备份当前版本... +if exist "dist" ( + if exist "dist_backup" ( + rmdir /s /q dist_backup + ) + xcopy /E /I /Y dist dist_backup >nul + echo [成功] 当前版本已备份到dist_backup目录 +) else ( + echo [警告] 未找到dist目录,跳过备份 +) + +:: 更新依赖 +echo [3/6] 更新项目依赖... +call npm install --production +if errorlevel 1 ( + echo [错误] 依赖更新失败 + pause + exit /b 1 +) + +:: 检查构建文件 +echo [4/6] 检查构建文件... +if not exist "dist\index.es.js" ( + echo [错误] 未找到构建文件,请确保已上传新版本的dist目录 + pause + exit /b 1 +) +echo [成功] 构建文件检查通过 + +:: 更新数据库(如果需要) +echo [5/6] 更新数据库... +echo [信息] 运行数据库更新脚本... +call npm run db:apply +if errorlevel 1 ( + echo [警告] 数据库更新失败,请检查数据库连接配置 + echo [提示] 可以稍后手动运行: npm run db:apply +) else ( + echo [成功] 数据库更新完成 +) + +:: 启动服务 +echo [6/6] 启动服务... +pm2 start ecosystem.config.cjs +if errorlevel 1 ( + echo [错误] 服务启动失败 + pause + exit /b 1 +) + +:: 显示服务状态 +echo ======================================== +echo 服务状态 +echo ======================================== +pm2 status + +echo ======================================== +echo 更新完成! +echo ======================================== +echo. +echo 常用命令: +echo 查看状态: pm2 status +echo 查看日志: pm2 logs web-bls-heartbeat-server +echo 重启服务: pm2 restart web-bls-heartbeat-server +echo 停止服务: pm2 stop web-bls-heartbeat-server +echo 实时监控: pm2 monit +echo. +pause \ No newline at end of file diff --git a/src/index.js b/src/index.js index 22fbea0..f94771d 100644 --- a/src/index.js +++ b/src/index.js @@ -28,6 +28,17 @@ class WebBLSHeartbeatServer { console.log('数据库连接成功'); await this.redis?.info('数据库连接成功', { module: 'db' }); + // 打印 Kafka 配置摘要,便于排查连接问题 + console.log('正在初始化 Kafka 消费者...'); + console.log('Kafka 配置:', { + brokers: this.config.kafka?.brokers, + topics: this.config.kafka?.topics, + groupId: this.config.kafka?.groupId, + fromOffset: this.config.kafka?.fromOffset ?? 'latest', + ssl: !!this.config.kafka?.sslEnabled, + sasl: !!this.config.kafka?.saslEnabled ? `enabled (mechanism: ${this.config.kafka?.saslMechanism})` : 'disabled' + }); + // 初始化处理器(共享批处理队列) this.heartbeatProcessor = new HeartbeatProcessor(this.config.processor, this.databaseManager); diff --git a/src/kafka/consumer.js b/src/kafka/consumer.js index f59c31a..211a3b4 100644 --- a/src/kafka/consumer.js +++ b/src/kafka/consumer.js @@ -52,7 +52,7 @@ class KafkaConsumer { autoCommit: false, autoCommitIntervalMs: this.config.autoCommitIntervalMs, // 从最新开始(生产环境常见);需要历史消费可改 earliest - fromOffset: 'latest', + fromOffset: this.config.fromOffset ?? 'latest', encoding: 'buffer', keyEncoding: 'buffer', }; diff --git a/vite.config.js b/vite.config.js index 93e24fb..6736acc 100644 --- a/vite.config.js +++ b/vite.config.js @@ -14,7 +14,7 @@ export default defineConfig({ 'kafka-node', 'pg', 'redis', // Node.js core modules 'events', 'url', 'crypto', 'util', 'net', 'tls', 'buffer', 'path', - 'node:zlib', + 'node:zlib', 'node:fs', 'node:path', 'node:url', // openspec is not actually used in the code, remove it ], output: {