123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- #!/usr/bin/env tsx
- /**
- * 生产环境完整交易系统启动器
- * Production Complete Trading System Launcher
- *
- * 基于 main-complete.ts 的生产级部署版本
- */
- import { CompleteTradingSystem } from './src/main-complete.js'
- import { ProductionLogger } from './src/utils/ProductionLogger.js'
- import * as fs from 'fs'
- import * as http from 'http'
- class ProductionSystemRunner {
- private system?: CompleteTradingSystem
- private logger: ProductionLogger
- private isShuttingDown = false
- private healthCheckServer?: http.Server
- private systemStartTime = Date.now()
- constructor() {
- this.logger = ProductionLogger.getInstance({
- level: (process.env.LOG_LEVEL as any) || 'info',
- enableFile: true,
- logDir: process.env.LOG_DIR || './logs',
- enableConsole: true,
- enableAudit: true,
- })
- }
- async start() {
- this.displayBanner()
- this.setupSignalHandlers()
- this.startHealthCheck()
- this.logger.info('🚀 启动生产级交易系统', {
- nodeEnv: process.env.NODE_ENV,
- pid: process.pid,
- memory: process.memoryUsage(),
- version: '1.0.0',
- })
- try {
- // 环境检查
- this.performEnvironmentCheck()
- // 创建并启动完整交易系统
- this.system = new CompleteTradingSystem()
- // 绑定生产环境监听器
- this.setupProductionEventHandlers()
- // 启动系统
- await this.system.start()
- this.logger.info('✅ 生产系统启动成功', {
- healthCheckUrl: 'http://localhost:3001/health',
- uptime: Date.now() - this.systemStartTime,
- })
- console.log(`
- ✅ 🚀 生产级交易系统已启动!
- 📊 监控地址:
- - 健康检查: http://localhost:3001/health
- - 系统状态: http://localhost:3001/status
- - 性能指标: http://localhost:3001/metrics
- 🔧 管理命令:
- - curl http://localhost:3001/health # 检查系统健康
- - kill -TERM ${process.pid} # 优雅关闭
- - kill -USR1 ${process.pid} # 重载配置
- 📁 日志位置: ${process.env.LOG_DIR || './logs'}
- `)
- // PM2 兼容性
- if (process.send) {
- process.send('ready')
- }
- // 保持运行并启动监控
- this.startSystemMonitoring()
- } catch (error: any) {
- this.logger.critical('❌ 生产系统启动失败', error)
- console.error('❌ 生产系统启动失败:', error.message)
- process.exit(1)
- }
- }
- private displayBanner() {
- console.log(`
- ██████ ██████ ██████ ██████ ██ ██ ██████ ████████ ██ ██████ ███ ██
- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
- ██████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
- ██ ██ ██ ██████ ██████ ██████ ██████ ██ ██ ██████ ██ ████
- 🌟 生产级完整交易系统 v1.0.0
- 🔥 多平台对冲 | 实时监控 | 自动化交易 | 风险控制
- 启动时间: ${new Date().toLocaleString('zh-CN')}
- 进程 ID: ${process.pid}
- Node.js: ${process.version}
- 内存: ${Math.round(process.memoryUsage().rss / 1024 / 1024)}MB
- `)
- }
- private performEnvironmentCheck() {
- const required = ['NODE_ENV']
- const missing = required.filter(env => !process.env[env])
- if (missing.length > 0) {
- this.logger.warn('⚠️ 缺少环境变量', { missingVars: missing })
- }
- // 检查日志目录
- const logDir = process.env.LOG_DIR || './logs'
- if (!fs.existsSync(logDir)) {
- fs.mkdirSync(logDir, { recursive: true })
- this.logger.info('📁 创建日志目录', { logDir })
- }
- this.logger.info('✅ 环境检查完成', {
- nodeEnv: process.env.NODE_ENV,
- logDir,
- })
- }
- private startHealthCheck() {
- this.healthCheckServer = http.createServer((req, res) => {
- const url = req.url || ''
- // CORS 支持
- res.setHeader('Access-Control-Allow-Origin', '*')
- res.setHeader('Content-Type', 'application/json')
- if (url === '/health') {
- const health = {
- status: 'healthy',
- timestamp: new Date().toISOString(),
- uptime: process.uptime(),
- memory: process.memoryUsage(),
- pid: process.pid,
- system: this.system ? 'running' : 'starting',
- version: '1.0.0',
- }
- res.writeHead(200)
- res.end(JSON.stringify(health, null, 2))
- } else if (url === '/status' && this.system) {
- try {
- const stats = this.system.getSystemStats()
- res.writeHead(200)
- res.end(JSON.stringify(stats, null, 2))
- } catch (error: any) {
- res.writeHead(500)
- res.end(JSON.stringify({ error: error.message }))
- }
- } else if (url === '/metrics') {
- const metrics = {
- timestamp: new Date().toISOString(),
- uptime: process.uptime(),
- memory: process.memoryUsage(),
- cpu: process.cpuUsage(),
- startTime: this.systemStartTime,
- systemActive: !!this.system,
- }
- res.writeHead(200)
- res.end(JSON.stringify(metrics, null, 2))
- } else {
- res.writeHead(404)
- res.end(JSON.stringify({ error: 'Not Found' }))
- }
- })
- this.healthCheckServer.listen(3001, () => {
- console.log('🏥 健康检查服务器已启动: http://localhost:3001/health')
- })
- this.healthCheckServer.on('error', (error: any) => {
- this.logger.error('健康检查服务器错误', error)
- })
- }
- private setupProductionEventHandlers() {
- if (!this.system) return
- // 系统级事件
- this.system.on('error', (error: Error) => {
- this.logger.error('🚨 系统错误', error)
- if (error.message.includes('FATAL')) {
- this.logger.critical('💀 致命错误,准备重启', error)
- this.attemptSystemRestart()
- }
- })
- this.system.on('warning', (warning: string) => {
- this.logger.warn(`⚠️ 系统警告: ${warning}`)
- })
- // 交易事件
- this.system.on('trade_executed', (data: any) => {
- this.logger.trade('订单执行', {
- exchange: data.exchange,
- symbol: data.symbol,
- side: data.side,
- quantity: data.quantity,
- price: data.price,
- orderId: data.orderId,
- })
- })
- // 对冲事件
- this.system.on('hedge_executed', (data: any) => {
- this.logger.hedge('对冲执行', {
- sourceExchange: data.sourceExchange,
- targetExchange: data.targetExchange,
- symbol: data.symbol,
- quantity: data.quantity,
- reason: data.reason,
- })
- })
- }
- private startSystemMonitoring() {
- // 心跳检查 (每分钟)
- const heartbeatInterval = setInterval(async () => {
- if (this.isShuttingDown) {
- clearInterval(heartbeatInterval)
- return
- }
- try {
- if (this.system) {
- const stats = await this.system.getSystemStats()
- this.logger.info('💓 系统心跳', {
- accounts: stats.accounts.total,
- connections: stats.connections.active,
- dailyTrades: stats.trading.dailyTrades,
- uptime: Math.round(process.uptime()),
- })
- }
- } catch (error: any) {
- this.logger.warn(`心跳检查失败: ${error.message}`)
- }
- }, 60000)
- // 内存监控 (每30秒)
- const memoryInterval = setInterval(() => {
- if (this.isShuttingDown) {
- clearInterval(memoryInterval)
- return
- }
- const usage = process.memoryUsage()
- const memoryMB = Math.round(usage.rss / 1024 / 1024)
- this.logger.performance('内存使用', memoryMB, {
- heap: Math.round(usage.heapUsed / 1024 / 1024),
- external: Math.round(usage.external / 1024 / 1024),
- })
- // 内存警告
- if (memoryMB > 500) {
- this.logger.warn(`⚠️ 内存使用过高: ${memoryMB}MB`)
- }
- // 内存泄漏检测
- if (memoryMB > 1000) {
- this.logger.critical(`🚨 内存可能泄漏: ${memoryMB}MB`)
- }
- }, 30000)
- }
- private setupSignalHandlers() {
- // 优雅关闭信号
- ;['SIGTERM', 'SIGINT'].forEach(signal => {
- process.on(signal, () => {
- console.log(`\n🛑 收到 ${signal} 信号,开始优雅关闭...`)
- this.gracefulShutdown()
- })
- })
- // 重载配置信号 (生产环境热更新)
- process.on('SIGUSR1', () => {
- this.logger.info('🔄 收到重载配置信号')
- this.reloadConfiguration()
- })
- // 错误处理
- process.on('uncaughtException', error => {
- this.logger.critical('💥 未捕获异常', error)
- console.error('💥 未捕获异常:', error)
- this.gracefulShutdown()
- })
- process.on('unhandledRejection', reason => {
- this.logger.critical('💥 未处理的Promise拒绝', undefined, { reason })
- console.error('💥 未处理的Promise拒绝:', reason)
- })
- }
- private async attemptSystemRestart() {
- this.logger.info('🔄 尝试系统自动恢复...')
- try {
- if (this.system) {
- await this.system.shutdown()
- this.system = undefined
- }
- // 等待5秒
- await new Promise(resolve => setTimeout(resolve, 5000))
- // 重新创建系统
- this.system = new CompleteTradingSystem()
- this.setupProductionEventHandlers()
- await this.system.start()
- this.logger.info('✅ 系统自动恢复成功')
- } catch (error: any) {
- this.logger.critical('❌ 系统自动恢复失败', error)
- process.exit(1)
- }
- }
- private async reloadConfiguration() {
- try {
- this.logger.info('🔧 开始重载配置...')
- // 这里可以实现配置热更新逻辑
- // 例如重新读取环境变量、配置文件等
- this.logger.info('✅ 配置重载完成')
- } catch (error: any) {
- this.logger.error('❌ 配置重载失败', error)
- }
- }
- private async gracefulShutdown() {
- if (this.isShuttingDown) return
- this.isShuttingDown = true
- const shutdownStart = Date.now()
- try {
- this.logger.info('🛑 开始优雅关闭系统...')
- // 1. 停止接受新请求
- if (this.healthCheckServer) {
- this.healthCheckServer.close()
- this.logger.info('✅ 健康检查服务器已关闭')
- }
- // 2. 关闭交易系统
- if (this.system) {
- await this.system.shutdown()
- this.logger.info('✅ 交易系统已关闭')
- }
- // 3. 等待现有操作完成 (最多30秒)
- const maxWait = 30000
- const remaining = maxWait - (Date.now() - shutdownStart)
- if (remaining > 0) {
- this.logger.info(`⏱️ 等待现有操作完成... (最多${remaining}ms)`)
- await new Promise(resolve => setTimeout(resolve, Math.min(remaining, 5000)))
- }
- const shutdownTime = Date.now() - shutdownStart
- this.logger.info(`✅ 系统优雅关闭完成 (用时${shutdownTime}ms)`)
- // 关闭日志系统
- this.logger.close()
- process.exit(0)
- } catch (error: any) {
- this.logger.critical('❌ 优雅关闭失败', error)
- console.error('❌ 优雅关闭失败:', error)
- process.exit(1)
- }
- }
- }
- // 启动生产系统
- if (import.meta.url === `file://${process.argv[1]}`) {
- // 设置默认环境变量
- process.env.NODE_ENV = process.env.NODE_ENV || 'production'
- const runner = new ProductionSystemRunner()
- runner.start().catch(error => {
- console.error('❌ 系统启动失败:', error)
- process.exit(1)
- })
- }
- export { ProductionSystemRunner }
|