UNPKG

multi-lane-manager

Version:

Nacos 泳道管理与请求路由组件

212 lines (181 loc) 7.73 kB
import type { H3Event } from 'h3'; // 使用 any 类型来避免 TypeScript 类型错误 // 因为 NitroApp 的类型定义可能与实际使用的不一致 import type { NitroApp as OriginalNitroApp } from 'nitropack'; type NitroApp = OriginalNitroApp & { options?: { runtimeConfig?: { appName?: string; public?: { appName?: string; }; }; }; }; import { getConfig, getGlobalState, updateConfigPort } from '../utils/config'; import { logger } from '../utils/logger'; import { registerServiceInstance, deregisterServiceInstance } from '../utils/nacos'; import { getServerPort } from './server-utils'; /** * Nitro 插件 - 泳道管理服务注册 * * 此插件在 Nitro 服务器启动时执行,负责: * 1. 获取服务器端口 * 2. 注册服务实例到 Nacos * 3. 设置服务器关闭时的注销逻辑 * 4. 提供健康检查接口 */ // 在模块加载时立即执行的代码 logger.info(`====== 🚀 泳道管理 Nitro 插件模块被加载 ======`); logger.debug(`⏱️ 当前时间: ${new Date().toISOString()}`); logger.debug(`🆔 当前进程ID: ${process.pid}`); logger.debug(`📂 当前工作目录: ${process.cwd()}`); logger.debug(`🔧 环境变量: NODE_ENV=${process.env.NODE_ENV}, NITRO_PORT=${process.env.NITRO_PORT || '未设置'}, PORT=${process.env.PORT || '未设置'}`); // 初始化全局状态 const globalState = getGlobalState(); if (!globalState._laneMgrRegistered) { globalState._laneMgrRegistered = false; globalState._laneMgrPort = undefined; logger.debug(`🔄 初始化全局注册状态为 false`); } else { logger.debug(`ℹ️ 全局注册状态已存在: ${globalState._laneMgrRegistered}`); } /** * Nitro 插件主函数 * 在 Nitro 服务器启动时执行,负责服务注册和健康检查 * * @param nitroApp Nitro 应用实例 */ export default async (nitroApp: NitroApp) => { logger.info(`====== 🔌 泳道管理 Nitro 插件函数被调用 ======`); logger.debug(`⏱️ 当前时间: ${new Date().toISOString()}`); logger.debug(`✅ nitroApp 对象可用: ${!!nitroApp}`); logger.debug(`✅ nitroApp.hooks 可用: ${!!nitroApp.hooks}`); // 导入中间件 try { const { default: middleware } = await import('./server-middleware'); logger.info(`✅ 成功导入中间件`); // 添加中间件到 Nitro 应用 nitroApp.hooks.hook('request', middleware); logger.info(`✅ 成功添加中间件到 Nitro 应用`); } catch (error) { logger.error(`❌ 导入或添加中间件失败: ${error instanceof Error ? error.message : String(error)}`); } // 尝试从Nitro运行时配置获取应用名称 try { if (nitroApp.options && nitroApp.options.runtimeConfig) { const appName = nitroApp.options.runtimeConfig.appName || (nitroApp.options.runtimeConfig.public && nitroApp.options.runtimeConfig.public.appName); if (appName) { // 将应用名称存储在全局变量中,以便在其他地方使用 (global as any).__nitroAppName = appName; logger.info(`✅ 从Nitro运行时配置获取应用名称: ${appName}`); // 清除配置缓存,强制下次获取配置时重新创建 // 这样可以确保使用最新的应用名称 const { clearConfigCache } = await import('../utils/config'); clearConfigCache(); } } } catch (error) { logger.warn(`⚠️ 无法从Nitro运行时配置获取应用名称: ${error}`); } // 立即注册服务 (async () => { logger.info(`====== 📝 开始注册服务 ======`); try { // 如果已经注册过,则跳过 if (globalState._laneMgrRegistered) { logger.info(`ℹ️ 服务已注册,跳过重复注册`); return; } // 获取服务器端口 const port = getServerPort(); // 更新配置中的端口 updateConfigPort(port); // 标记为已注册,避免重复注册 globalState._laneMgrRegistered = true; globalState._laneMgrPort = port; // 注册服务实例 logger.info(`📤 开始注册服务到 Nacos,端口: ${port}`); const success = await registerServiceInstance(port); logger.info(`📋 服务注册结果: ${success ? '✅ 成功' : '❌ 失败'}`); if (success) { // 设置服务器关闭时的注销逻辑 const gracefulShutdown = async () => { logger.info(`🛑 服务器关闭,正在注销服务...`); await deregisterServiceInstance(port); logger.info(`✅ 服务注销完成`); }; // 监听进程退出事件 process.on('beforeExit', gracefulShutdown); process.on('SIGINT', async () => { logger.info(`🔴 收到 SIGINT 信号`); await gracefulShutdown(); process.exit(0); }); process.on('SIGTERM', async () => { logger.info(`🔴 收到 SIGTERM 信号`); await gracefulShutdown(); process.exit(0); }); // 监听 Nitro 关闭事件 nitroApp.hooks.hook('close', async () => { logger.info(`🔴 收到 Nitro close 事件`); await gracefulShutdown(); }); logger.info(`✅ 已设置服务注销钩子`); } } catch (error) { logger.error(`❌ 服务注册过程中出错:`, error); } })(); // 添加请求处理钩子,确保能拦截所有请求,包括静态资源 nitroApp.hooks.hook('request', async (event: H3Event) => { // 检查请求是否已经被处理过,避免重复处理 if (event.context._laneManagerHandled || event.context._laneManagerProcessing) { return; } // 记录所有请求,确保插件被触发 console.log(`[multi-lane-manager:nitro-plugin] Intercepting request: ${event.path}`); // 特别记录 /_nuxt/ 路径的请求 if (event.path.startsWith('/_nuxt/')) { console.log(`[multi-lane-manager:nitro-plugin] Intercepting _nuxt request1: ${event.path}`); logger.info(`🔍 Nitro插件拦截到静态资源请求: ${event.path}`); } // 特别记录 /api/ 路径的请求 if (event.path.startsWith('/api/')) { console.log(`[multi-lane-manager:nitro-plugin] Intercepting API request: ${event.path}`); logger.info(`🔍 Nitro插件拦截到API请求: ${event.path}, 方法: ${event.node.req.method}`); } // 如果请求路径是 /api/lane-manager/health,则返回健康状态 if (event.path === '/api/lane-manager/health') { // 标记请求正在被处理,避免重复处理 event.context._laneManagerProcessing = true; logger.debug(`🩺 收到健康检查请求: ${event.path}`); // 获取当前配置 const config = getConfig(); try { // 设置响应 if (!event.node.res.headersSent) { event.node.res.statusCode = 200; event.node.res.setHeader('Content-Type', 'application/json'); // 返回健康状态信息 event.node.res.end(JSON.stringify({ status: 'ok', registered: globalState._laneMgrRegistered || false, port: globalState._laneMgrPort || null, laneId: config.currentLaneId, serviceName: config.serviceName, timestamp: new Date().toISOString(), nitroPluginLoaded: true })); } } catch (error) { logger.error(`❌ 处理健康检查请求时出错: ${error instanceof Error ? error.message : String(error)}`); } // 标记请求已处理 event.context._laneManagerHandled = true; } }); logger.info(`====== ✅ 泳道管理 Nitro 插件初始化完成 ======`); };