multi-lane-manager
Version:
Nacos 泳道管理与请求路由组件
1 lines • 28.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils/config.ts"],"sourcesContent":["import * as os from 'os';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { logger } from './logger';\nimport {\n DEFAULT_LANE_SERVER,\n DEFAULT_LANE_NAMESPACE,\n DEFAULT_LANE_GROUP_NAME,\n DEFAULT_LANE_HEARTBEAT_INTERVAL,\n DEFAULT_LANE_INSTANCE_TTL,\n DEFAULT_SERVICE_NAME,\n DEFAULT_LANE_ID,\n DEFAULT_HOST,\n DEFAULT_LANE_TARGET_HEADER,\n DEFAULT_LANE_ENABLED,\n DEFAULT_LANE_COOKIE_ENABLED,\n DEFAULT_LANE_PROXY_TIMEOUT,\n DEFAULT_LANE_REGISTRATION_TIMEOUT,\n DEFAULT_NACOS_CACHE_TTL,\n getEnvOrDefault,\n getBooleanEnv,\n getNumberEnv\n} from './defaults';\n\n/**\n * 检查IP地址是否为私有网络地址\n * @param ip IP地址\n * @returns 是否为私有网络地址\n */\nfunction isPrivateIP(ip: string): boolean {\n // 私有网络地址范围:\n // 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)\n // 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)\n // 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)\n\n const parts = ip.split('.').map(Number);\n if (parts.length !== 4) return false;\n\n const [a, b] = parts;\n\n return (\n a === 10 ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168)\n );\n}\n\n/**\n * 检查IP地址是否应该被跳过\n * @param ip IP地址\n * @param interfaceName 网络接口名称\n * @returns 是否应该跳过\n */\nfunction shouldSkipIP(ip: string, interfaceName: string): boolean {\n // 跳过Docker桥接网络(通常是172.17.x.x)\n if (ip.startsWith('172.17.')) {\n logger.debug(`⏭️ 跳过Docker桥接网络地址: ${ip} (接口: ${interfaceName})`);\n return true;\n }\n\n // 跳过Docker默认网络(通常是172.18.x.x到172.31.x.x)\n const parts = ip.split('.').map(Number);\n if (parts[0] === 172 && parts[1] >= 17 && parts[1] <= 31) {\n logger.debug(`⏭️ 跳过Docker网络地址: ${ip} (接口: ${interfaceName})`);\n return true;\n }\n\n // 跳过某些虚拟接口\n const skipInterfaces = ['docker0', 'br-', 'veth'];\n if (skipInterfaces.some(skip => interfaceName.startsWith(skip))) {\n logger.debug(`⏭️ 跳过虚拟接口: ${interfaceName} (IP: ${ip})`);\n return true;\n }\n\n return false;\n}\n\n/**\n * 自动检测当前实例的IP地址\n * 完全自动化,无需手动配置,遵循容器/K8s最佳实践\n *\n * @returns 检测到的IP地址\n */\nfunction detectInstanceIP(): string {\n logger.info(`🔍 开始自动检测实例IP地址...`);\n\n // 1. 自动检测网络接口(核心逻辑)\n try {\n const networkInterfaces = os.networkInterfaces();\n logger.debug(`🔍 检测到的网络接口: ${JSON.stringify(Object.keys(networkInterfaces))}`);\n\n // 容器环境优先的网络接口(按优先级排序)\n const containerInterfaces = [\n 'eth0', // 最常见的容器网络接口\n 'eth1', // 多网卡容器\n 'ens3', // 云环境常见接口\n 'ens4', // 云环境常见接口\n ];\n\n // 物理机/虚拟机环境的网络接口\n const physicalInterfaces = [\n 'ens160', // VMware虚拟机\n 'ens192', // VMware虚拟机\n 'enp0s3', // VirtualBox\n 'enp0s8', // VirtualBox\n 'en0', // macOS\n 'en1', // macOS\n 'wlan0', // 无线网络\n ];\n\n // 首先尝试容器环境的网络接口\n for (const interfaceName of containerInterfaces) {\n const networkInterface = networkInterfaces[interfaceName];\n if (networkInterface) {\n for (const addr of networkInterface) {\n if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {\n logger.info(`✅ 从容器网络接口 ${interfaceName} 获取IP地址: ${addr.address}`);\n return addr.address;\n }\n }\n }\n }\n\n // 然后尝试物理机/虚拟机的网络接口\n for (const interfaceName of physicalInterfaces) {\n const networkInterface = networkInterfaces[interfaceName];\n if (networkInterface) {\n for (const addr of networkInterface) {\n if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {\n logger.info(`✅ 从物理网络接口 ${interfaceName} 获取IP地址: ${addr.address}`);\n return addr.address;\n }\n }\n }\n }\n\n // 最后遍历所有接口,寻找合适的IP\n const candidateIPs: Array<{ip: string, interface: string, isPrivate: boolean}> = [];\n\n for (const [interfaceName, addresses] of Object.entries(networkInterfaces)) {\n if (!addresses) continue;\n\n for (const addr of addresses) {\n if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {\n candidateIPs.push({\n ip: addr.address,\n interface: interfaceName,\n isPrivate: isPrivateIP(addr.address)\n });\n }\n }\n }\n\n if (candidateIPs.length > 0) {\n // 优先选择私有网络IP(容器/K8s环境通常使用私有网络)\n const privateIPs = candidateIPs.filter(candidate => candidate.isPrivate);\n if (privateIPs.length > 0) {\n const selected = privateIPs[0];\n logger.info(`✅ 选择私有网络IP: ${selected.ip} (接口: ${selected.interface})`);\n return selected.ip;\n }\n\n // 如果没有私有网络IP,选择第一个可用的IP\n const selected = candidateIPs[0];\n logger.info(`✅ 选择公网IP: ${selected.ip} (接口: ${selected.interface})`);\n return selected.ip;\n }\n\n } catch (error) {\n logger.warn(`⚠️ 自动检测网络接口失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // 2. 检查Kubernetes环境变量(作为备选方案)\n if (process.env.POD_IP && process.env.POD_IP !== 'localhost' && process.env.POD_IP !== '127.0.0.1') {\n logger.info(`🎯 网络接口检测失败,使用Kubernetes Pod IP: ${process.env.POD_IP}`);\n return process.env.POD_IP;\n }\n\n // 3. 检查其他容器环境变量(最后的备选方案)\n if (process.env.CONTAINER_IP && process.env.CONTAINER_IP !== 'localhost' && process.env.CONTAINER_IP !== '127.0.0.1') {\n logger.info(`📦 网络接口检测失败,使用容器环境变量IP: ${process.env.CONTAINER_IP}`);\n return process.env.CONTAINER_IP;\n }\n\n // 4. 如果都没有找到,使用默认值并记录详细的建议\n logger.error(`❌ 无法自动检测到有效的IP地址!`);\n logger.error(`💡 这通常发生在以下情况:`);\n logger.error(` 1. 容器网络配置异常`);\n logger.error(` 2. 网络接口名称不在预期范围内`);\n logger.error(` 3. 所有检测到的IP都被过滤掉了`);\n logger.error(`🔧 解决方案:`);\n logger.error(` - 在Kubernetes中使用Downward API注入POD_IP`);\n logger.error(` - 检查容器网络配置`);\n logger.error(` - 如果必要,可以设置HOST环境变量作为临时解决方案`);\n\n return DEFAULT_HOST;\n}\n\n/**\n * 泳道管理器配置接口\n * 定义了泳道管理器所需的所有配置项\n */\nexport interface LaneManagerConfig {\n // Nacos 服务器配置\n nacosServerAddr: string; // Nacos 服务器地址(从 NACOS_SERVER 解析)\n nacosServerPort: string; // Nacos 服务器端口(从 NACOS_SERVER 解析)\n nacosUrl: string; // 完整的 Nacos 服务器 URL\n nacosNamespace: string; // Nacos 命名空间\n nacosGroupName: string; // Nacos 分组名称\n\n // 服务配置\n serviceName: string; // 当前服务名称\n currentLaneId: string; // 当前泳道 ID\n host: string; // 服务主机名\n port: number | null; // 服务端口,初始为 null\n\n // 泳道配置\n targetLaneHeaderKey: string; // 目标泳道请求头键名(小写形式)\n isLaneEnabled: boolean; // 是否启用泳道功能\n isLaneCookieEnabled: boolean; // 是否启用从cookie中检测泳道ID\n\n // 超时配置\n proxyTimeout: number; // 代理请求超时时间(毫秒)\n registrationTimeout: number; // 注册请求超时时间(毫秒)\n heartbeatInterval: number; // 心跳间隔时间(毫秒)\n instanceTtl: number; // 实例过期时间(毫秒)\n\n // 缓存配置\n nacosCacheTtl: number; // Nacos 实例查询缓存时间(毫秒)\n\n // 元数据\n metadata: Record<string, any>; // 服务实例元数据\n}\n\n// 配置缓存,避免重复创建配置对象\nlet configCache: LaneManagerConfig | null = null;\n\n/**\n * 获取配置,优先使用缓存\n * @returns 泳道管理器配置对象\n */\nexport function getConfig(): LaneManagerConfig {\n if (configCache) {\n return configCache;\n }\n\n // 创建新配置\n configCache = createConfig();\n return configCache;\n}\n\n/**\n * 清除配置缓存,强制下次获取时重新创建\n * 在配置需要重新加载时调用\n */\nexport function clearConfigCache(): void {\n configCache = null;\n logger.debug('🔄 配置缓存已清除');\n}\n\n/**\n * 创建配置对象\n * 从环境变量中读取配置,并设置默认值\n * @returns 新创建的配置对象\n */\nfunction createConfig(): LaneManagerConfig {\n // 从环境变量读取基本配置,并设置默认值\n const nacosServer = process.env.LANE_SERVER || process.env.NACOS_SERVER || DEFAULT_LANE_SERVER;\n logger.debug(`🔍 Nacos服务器配置: LANE_SERVER=${process.env.LANE_SERVER}, NACOS_SERVER=${process.env.NACOS_SERVER}, DEFAULT_LANE_SERVER=${DEFAULT_LANE_SERVER}`);\n logger.debug(`🔍 最终使用的Nacos服务器: ${nacosServer}`);\n\n // 解析Nacos服务器地址和端口\n const parts = nacosServer.split(':');\n const nacosServerAddr = parts[0] || 'localhost';\n const nacosServerPort = parts.length > 1 ? parts[1] : '8848';\n logger.debug(`🔍 解析后的Nacos地址: ${nacosServerAddr}, 端口: ${nacosServerPort}`);\n\n // 服务名称获取详细过程\n logger.debug(`🔍 服务名称获取过程开始...`);\n logger.debug(`🔍 环境变量 SERVICE_NAME=${process.env.SERVICE_NAME}`);\n logger.debug(`🔍 DEFAULT_SERVICE_NAME=${DEFAULT_SERVICE_NAME}`);\n\n // 检查 package.json 中的 name\n let packageJsonName = '未检测';\n try {\n // 尝试从多个可能的位置读取 package.json\n const possiblePaths = [\n // 优先检查 server/package.json (适用于 node server/index.mjs 启动方式)\n path.resolve(process.cwd(), 'server', 'package.json'),\n\n // 当前工作目录\n path.resolve(process.cwd(), 'package.json'),\n\n // 当前工作目录的父目录(可能是项目根目录)\n path.resolve(process.cwd(), '..', 'package.json'),\n\n // 常见的服务器输出目录\n path.resolve(process.cwd(), 'server', '..', 'package.json'),\n path.resolve(process.cwd(), '.output', 'server', '..', 'package.json'),\n path.resolve(process.cwd(), 'dist', '..', 'package.json'),\n path.resolve(process.cwd(), 'build', '..', 'package.json'),\n\n // Nuxt输出目录\n path.resolve(process.cwd(), '.output', 'package.json'),\n\n // 应用根目录(如果设置了APP_ROOT环境变量)\n ...(process.env.APP_ROOT ? [path.resolve(process.env.APP_ROOT, 'package.json')] : []),\n\n // 向上查找两级目录\n path.resolve(process.cwd(), '..', '..', 'package.json'),\n ];\n\n // 尝试每个可能的路径\n for (const packageJsonPath of possiblePaths) {\n if (fs.existsSync(packageJsonPath)) {\n logger.debug(`🔍 尝试读取 package.json: ${packageJsonPath}`);\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n if (packageJson && packageJson.name) {\n packageJsonName = packageJson.name;\n logger.debug(`✅ 成功从 ${packageJsonPath} 读取到 package.json,name: ${packageJsonName}`);\n\n // 如果是从 server/package.json 获取的,特别标记一下\n if (packageJsonPath.includes('server/package.json')) {\n logger.info(`🚀 从 server/package.json 获取服务名称,适用于 node server/index.mjs 启动方式`);\n }\n\n break;\n } else {\n logger.debug(`⚠️ 从 ${packageJsonPath} 读取到 package.json,但没有 name 字段`);\n }\n }\n }\n } catch (error) {\n packageJsonName = `检测出错: ${error instanceof Error ? error.message : String(error)}`;\n logger.debug(`❌ 读取 package.json 失败: ${packageJsonName}`);\n }\n logger.debug(`🔍 package.json name=${packageJsonName}`);\n\n // 优先从环境变量获取服务名称,然后从 package.json 获取\n let serviceName = '';\n if (process.env.SERVICE_NAME) {\n serviceName = process.env.SERVICE_NAME;\n logger.info(`✅ 从环境变量 SERVICE_NAME 获取服务名称: ${serviceName}`);\n } else if (process.env.NITRO_APP_NAME) {\n serviceName = process.env.NITRO_APP_NAME;\n logger.info(`✅ 从环境变量 NITRO_APP_NAME 获取服务名称: ${serviceName}`);\n } else if (process.env.APP_NAME) {\n serviceName = process.env.APP_NAME;\n logger.info(`✅ 从环境变量 APP_NAME 获取服务名称: ${serviceName}`);\n } else if (process.env.npm_package_name) {\n serviceName = process.env.npm_package_name;\n logger.info(`✅ 从环境变量 npm_package_name 获取服务名称: ${serviceName}`);\n } else if (packageJsonName && packageJsonName !== '未检测' && packageJsonName !== '未设置' && !packageJsonName.startsWith('检测出错')) {\n serviceName = packageJsonName;\n logger.info(`✅ 从 package.json 获取服务名称: ${serviceName}`);\n } else {\n // 没有找到服务名称\n serviceName = '';\n logger.error(`❌ 警告: 无法获取服务名称,泳道功能将被禁用`);\n logger.error(`❌ 请通过以下方式之一设置服务名称:`);\n logger.error(` 1. 设置环境变量 SERVICE_NAME`);\n logger.error(` 2. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);\n logger.error(` 3. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);\n }\n logger.debug(`🔍 最终使用的服务名称: ${serviceName || '未设置 (泳道功能将被禁用)'}`);\n const currentLaneId = getEnvOrDefault('LANE_ID', DEFAULT_LANE_ID);\n\n // 使用智能IP检测\n logger.debug(`🔍 开始检测实例IP地址...`);\n const host = detectInstanceIP();\n logger.info(`🌐 最终使用的IP地址: ${host}`);\n\n // 创建服务实例元数据\n const metadata = {\n laneId: currentLaneId, // 泳道 ID\n environment: getEnvOrDefault('NODE_ENV', 'development'), // 环境\n registeredAt: new Date().toISOString(), // 注册时间\n framework: 'nuxt3', // 框架\n version: getEnvOrDefault('npm_package_version', 'unknown'), // 版本\n hostname: os.hostname(), // 主机名\n nodeVersion: process.versions.node, // Node.js 版本\n };\n\n // 检查服务名称是否有效\n const hasValidServiceName = !!serviceName;\n\n // 检查泳道功能是否启用\n const isLaneEnabled = hasValidServiceName ? getBooleanEnv('LANE_ENABLE', DEFAULT_LANE_ENABLED) : false;\n\n // 如果泳道功能启用但没有有效的服务名称,则停止应用\n if (isLaneEnabled && !hasValidServiceName) {\n logger.error(`❌ 错误: 泳道功能已启用,但无法获取有效的服务名称,应用将停止启动`);\n logger.error(`❌ 请通过以下方式之一设置服务名称:`);\n logger.error(` 1. 设置环境变量 SERVICE_NAME`);\n logger.error(` 2. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);\n logger.error(` 3. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);\n\n // 停止应用\n process.exit(1);\n }\n\n // 如果没有有效的服务名称但泳道功能未启用,则只显示警告\n if (!hasValidServiceName && !isLaneEnabled) {\n logger.error(`❌ 警告: 无法获取有效的服务名称,已自动禁用泳道功能`);\n logger.error(`❌ 请通过以下方式之一设置服务名称:`);\n logger.error(` 1. 设置环境变量 SERVICE_NAME`);\n logger.error(` 2. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);\n logger.error(` 3. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);\n }\n\n // 创建完整配置对象\n const config: LaneManagerConfig = {\n // Nacos 服务器配置\n nacosServerAddr,\n nacosServerPort,\n nacosUrl: `http://${nacosServerAddr}:${nacosServerPort}`,\n nacosNamespace: getEnvOrDefault('LANE_NAMESPACE', process.env.NACOS_NAMESPACE || DEFAULT_LANE_NAMESPACE),\n nacosGroupName: getEnvOrDefault('LANE_GROUP_NAME', process.env.NACOS_GROUP_NAME || DEFAULT_LANE_GROUP_NAME),\n\n // 服务配置\n serviceName,\n currentLaneId,\n host,\n port: null, // 初始为 null,将在服务启动时设置\n\n // 泳道配置\n targetLaneHeaderKey: (() => {\n // 详细记录 targetLaneHeaderKey 的获取过程\n logger.debug(`🔍 目标泳道请求头键名获取过程开始...`);\n logger.debug(`🔍 环境变量 LANE_TARGET_HEADER=${process.env.LANE_TARGET_HEADER}`);\n logger.debug(`🔍 环境变量 TARGET_LANE_HEADER=${process.env.TARGET_LANE_HEADER}`);\n logger.debug(`🔍 默认值 DEFAULT_LANE_TARGET_HEADER=${DEFAULT_LANE_TARGET_HEADER}`);\n\n const headerKey = getEnvOrDefault('LANE_TARGET_HEADER', process.env.TARGET_LANE_HEADER || DEFAULT_LANE_TARGET_HEADER);\n logger.debug(`🔍 最终使用的目标泳道请求头键名: ${headerKey}`);\n\n return headerKey;\n })(),\n // 使用前面计算的 isLaneEnabled 值\n isLaneEnabled: (() => {\n logger.debug(`🔍 泳道功能启用状态: ${isLaneEnabled} (hasValidServiceName=${hasValidServiceName}, LANE_ENABLE=${process.env.LANE_ENABLE}, DEFAULT_LANE_ENABLED=${DEFAULT_LANE_ENABLED})`);\n return isLaneEnabled;\n })(),\n isLaneCookieEnabled: (() => {\n const enabled = getBooleanEnv('LANE_COOKIE_ENABLE', DEFAULT_LANE_COOKIE_ENABLED);\n logger.debug(`🔍 Cookie泳道检测启用状态: ${enabled} (LANE_COOKIE_ENABLE=${process.env.LANE_COOKIE_ENABLE}, DEFAULT_LANE_COOKIE_ENABLED=${DEFAULT_LANE_COOKIE_ENABLED})`);\n return enabled;\n })(),\n\n // 超时配置\n proxyTimeout: getNumberEnv('LANE_PROXY_TIMEOUT', process.env.PROXY_TIMEOUT ? parseInt(process.env.PROXY_TIMEOUT) : DEFAULT_LANE_PROXY_TIMEOUT),\n registrationTimeout: getNumberEnv('LANE_REGISTRATION_TIMEOUT', process.env.REGISTRATION_TIMEOUT ? parseInt(process.env.REGISTRATION_TIMEOUT) : DEFAULT_LANE_REGISTRATION_TIMEOUT),\n heartbeatInterval: getNumberEnv('LANE_HEARTBEAT_INTERVAL', process.env.NACOS_HEARTBEAT_INTERVAL ? parseInt(process.env.NACOS_HEARTBEAT_INTERVAL) : DEFAULT_LANE_HEARTBEAT_INTERVAL),\n instanceTtl: getNumberEnv('LANE_INSTANCE_TTL', process.env.NACOS_INSTANCE_TTL ? parseInt(process.env.NACOS_INSTANCE_TTL) : DEFAULT_LANE_INSTANCE_TTL),\n\n // 缓存配置\n nacosCacheTtl: getNumberEnv('NACOS_CACHE_TTL', process.env.LANE_CACHE_TTL ? parseInt(process.env.LANE_CACHE_TTL) : DEFAULT_NACOS_CACHE_TTL),\n\n // 元数据\n metadata,\n };\n\n // 记录配置信息\n logger.debug('🔧 已创建配置对象:', config);\n\n return config;\n}\n\n/**\n * 更新配置中的端口信息\n * 在服务启动后调用,设置实际的服务端口\n * @param port 服务端口\n */\nexport function updateConfigPort(port: number): void {\n if (!configCache) {\n configCache = createConfig();\n }\n\n configCache.port = port;\n logger.debug(`🔌 配置端口已更新: ${port}`);\n}\n\n/**\n * 全局状态接口\n * 定义了在全局对象上存储的泳道管理器状态\n */\nexport interface GlobalWithLaneManager {\n _laneMgrRegistered?: boolean; // 是否已注册服务\n _laneMgrPort?: number; // 服务端口\n _laneMgrHeartbeatTimer?: NodeJS.Timeout; // 心跳定时器\n _laneMgrHeartbeatCount?: number; // 心跳计数器,用于控制日志打印频率\n}\n\n/**\n * 获取全局状态对象\n * 用于在不同模块间共享状态\n * @returns 全局状态对象\n */\nexport function getGlobalState(): GlobalWithLaneManager {\n return global as unknown as GlobalWithLaneManager;\n}\n"],"mappings":"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","names":["networkInterfaces","selected"]}