feat(port): 实现智能端口管理系统
- 新增端口管理器类,支持端口分配、验证和缓存管理 - 实现环境优先级策略,根据环境自动选择合适的端口范围 - 集成租户识别系统,为每个租户分配独立端口 - 添加端口分配结果统计和历史记录查询功能 - 优化端口缓存机制,自动清理过期绑定
This commit is contained in:
357
src/utils/port-config-manager.ts
Normal file
357
src/utils/port-config-manager.ts
Normal file
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* 端口配置管理器
|
||||
* 集成环境变量和智能端口管理
|
||||
*/
|
||||
|
||||
import type { PortStrategy } from '@/lib/port-manager';
|
||||
import type { Environment } from '@/lib/port-strategy';
|
||||
|
||||
// 端口配置接口
|
||||
export interface PortEnvironmentConfig {
|
||||
// 基础配置
|
||||
strategy: 'auto' | 'manual' | 'tenant-based' | 'sequential';
|
||||
basePort: number;
|
||||
portRangeStart: number;
|
||||
portRangeEnd: number;
|
||||
|
||||
// 租户配置
|
||||
tenantPortOffset: number;
|
||||
environmentPortOffset: number;
|
||||
|
||||
// 行为配置
|
||||
autoDetect: boolean;
|
||||
strictMode: boolean;
|
||||
cacheEnabled: boolean;
|
||||
cacheExpiry: number;
|
||||
|
||||
// 开发服务器配置
|
||||
devHost: string;
|
||||
openBrowser: boolean;
|
||||
corsEnabled: boolean;
|
||||
httpsEnabled: boolean;
|
||||
}
|
||||
|
||||
// 配置验证结果
|
||||
export interface ConfigValidationResult {
|
||||
isValid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
recommendations: string[];
|
||||
}
|
||||
|
||||
// 端口配置管理器
|
||||
export class PortConfigManager {
|
||||
private config: PortEnvironmentConfig;
|
||||
private environment: Environment;
|
||||
|
||||
constructor() {
|
||||
this.environment = this.detectEnvironment();
|
||||
this.config = this.loadConfiguration();
|
||||
this.validateConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测当前环境
|
||||
*/
|
||||
private detectEnvironment(): Environment {
|
||||
// 在 Vite 配置阶段,import.meta.env 可能不可用,使用 process.env
|
||||
const nodeEnv = (typeof process !== 'undefined' ? process.env.NODE_ENV : undefined) ||
|
||||
(typeof import.meta !== 'undefined' && import.meta.env ? import.meta.env.NODE_ENV : undefined) ||
|
||||
'development';
|
||||
|
||||
switch (nodeEnv.toLowerCase()) {
|
||||
case 'production':
|
||||
case 'prod':
|
||||
return 'production';
|
||||
case 'test':
|
||||
case 'testing':
|
||||
return 'test';
|
||||
case 'staging':
|
||||
case 'stage':
|
||||
return 'staging';
|
||||
default:
|
||||
return 'development';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载配置
|
||||
*/
|
||||
private loadConfiguration(): PortEnvironmentConfig {
|
||||
// 获取环境变量的辅助函数
|
||||
const getEnv = (key: string, defaultValue?: string) => {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
return process.env[key];
|
||||
}
|
||||
if (typeof import.meta !== 'undefined' && import.meta.env) {
|
||||
return import.meta.env[key];
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
return {
|
||||
// 基础配置
|
||||
strategy: (getEnv('VITE_PORT_STRATEGY') as any) || 'auto',
|
||||
basePort: parseInt(getEnv('VITE_BASE_PORT') || '3000'),
|
||||
portRangeStart: parseInt(getEnv('VITE_PORT_RANGE_START') || '3000'),
|
||||
portRangeEnd: parseInt(getEnv('VITE_PORT_RANGE_END') || '9999'),
|
||||
|
||||
// 租户配置
|
||||
tenantPortOffset: parseInt(getEnv('VITE_TENANT_PORT_OFFSET') || '10'),
|
||||
environmentPortOffset: parseInt(getEnv('VITE_ENVIRONMENT_PORT_OFFSET') || '1000'),
|
||||
|
||||
// 行为配置
|
||||
autoDetect: getEnv('VITE_PORT_AUTO_DETECT') !== 'false',
|
||||
strictMode: getEnv('VITE_PORT_STRICT_MODE') === 'true',
|
||||
cacheEnabled: getEnv('VITE_PORT_CACHE_ENABLED') !== 'false',
|
||||
cacheExpiry: parseInt(getEnv('VITE_PORT_CACHE_EXPIRY') || '86400000'), // 24小时
|
||||
|
||||
// 开发服务器配置
|
||||
devHost: getEnv('VITE_DEV_HOST') || 'localhost',
|
||||
openBrowser: getEnv('VITE_DEV_OPEN_BROWSER') !== 'false',
|
||||
corsEnabled: getEnv('VITE_DEV_CORS_ENABLED') !== 'false',
|
||||
httpsEnabled: getEnv('VITE_DEV_HTTPS_ENABLED') === 'true'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证配置
|
||||
*/
|
||||
private validateConfiguration(): ConfigValidationResult {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
const recommendations: string[] = [];
|
||||
|
||||
// 验证端口范围
|
||||
if (this.config.portRangeStart >= this.config.portRangeEnd) {
|
||||
errors.push('端口范围无效:起始端口必须小于结束端口');
|
||||
}
|
||||
|
||||
if (this.config.portRangeStart < 1024 && this.environment === 'production') {
|
||||
warnings.push('生产环境使用系统端口(<1024)可能需要管理员权限');
|
||||
}
|
||||
|
||||
// 验证基础端口
|
||||
if (this.config.basePort < this.config.portRangeStart ||
|
||||
this.config.basePort > this.config.portRangeEnd) {
|
||||
errors.push('基础端口不在允许的端口范围内');
|
||||
}
|
||||
|
||||
// 验证租户偏移
|
||||
if (this.config.tenantPortOffset <= 0) {
|
||||
warnings.push('租户端口偏移为0可能导致端口冲突');
|
||||
}
|
||||
|
||||
// 环境特定验证
|
||||
switch (this.environment) {
|
||||
case 'development':
|
||||
if (this.config.httpsEnabled) {
|
||||
warnings.push('开发环境启用HTTPS可能增加配置复杂度');
|
||||
}
|
||||
if (!this.config.autoDetect) {
|
||||
recommendations.push('开发环境建议启用端口自动检测');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'production':
|
||||
if (!this.config.httpsEnabled) {
|
||||
warnings.push('生产环境建议启用HTTPS');
|
||||
}
|
||||
if (this.config.autoDetect) {
|
||||
warnings.push('生产环境不建议启用端口自动检测');
|
||||
}
|
||||
if (!this.config.strictMode) {
|
||||
recommendations.push('生产环境建议启用严格模式');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'test':
|
||||
if (this.config.openBrowser) {
|
||||
recommendations.push('测试环境建议禁用自动打开浏览器');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 缓存配置验证
|
||||
if (this.config.cacheEnabled && this.config.cacheExpiry < 60000) {
|
||||
warnings.push('缓存过期时间过短可能影响性能');
|
||||
}
|
||||
|
||||
const result = {
|
||||
isValid: errors.length === 0,
|
||||
errors,
|
||||
warnings,
|
||||
recommendations
|
||||
};
|
||||
|
||||
// 输出验证结果
|
||||
if (errors.length > 0) {
|
||||
console.error('❌ 端口配置验证失败:', errors);
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
console.warn('⚠️ 端口配置警告:', warnings);
|
||||
}
|
||||
if (recommendations.length > 0) {
|
||||
console.info('💡 端口配置建议:', recommendations);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前配置
|
||||
*/
|
||||
getConfig(): PortEnvironmentConfig {
|
||||
return { ...this.config };
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取端口策略配置
|
||||
*/
|
||||
getPortStrategy(): PortStrategy {
|
||||
return {
|
||||
basePort: this.config.basePort,
|
||||
portRange: [this.config.portRangeStart, this.config.portRangeEnd],
|
||||
tenantOffset: this.config.tenantPortOffset,
|
||||
environmentOffset: this.config.environmentPortOffset,
|
||||
maxRetries: this.config.strictMode ? 10 : 50
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开发服务器配置
|
||||
*/
|
||||
getDevServerConfig(): {
|
||||
host: string;
|
||||
port?: number;
|
||||
open: boolean;
|
||||
cors: boolean;
|
||||
https: boolean;
|
||||
strictPort: boolean;
|
||||
} {
|
||||
return {
|
||||
host: this.config.devHost,
|
||||
open: this.config.openBrowser,
|
||||
cors: this.config.corsEnabled,
|
||||
https: this.config.httpsEnabled,
|
||||
strictPort: this.config.strictMode
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取环境信息
|
||||
*/
|
||||
getEnvironmentInfo(): {
|
||||
current: Environment;
|
||||
config: PortEnvironmentConfig;
|
||||
validation: ConfigValidationResult;
|
||||
recommendations: string[];
|
||||
} {
|
||||
const validation = this.validateConfiguration();
|
||||
const recommendations: string[] = [];
|
||||
|
||||
// 基于环境生成建议
|
||||
switch (this.environment) {
|
||||
case 'development':
|
||||
recommendations.push('开发环境:优先考虑便利性和调试体验');
|
||||
recommendations.push('建议启用热重载和自动刷新功能');
|
||||
break;
|
||||
case 'test':
|
||||
recommendations.push('测试环境:注重隔离性和可重复性');
|
||||
recommendations.push('建议配置独立的端口范围避免冲突');
|
||||
break;
|
||||
case 'production':
|
||||
recommendations.push('生产环境:优先考虑安全性和稳定性');
|
||||
recommendations.push('建议使用固定端口和负载均衡');
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
current: this.environment,
|
||||
config: this.config,
|
||||
validation,
|
||||
recommendations: [...validation.recommendations, ...recommendations]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新配置
|
||||
*/
|
||||
updateConfig(updates: Partial<PortEnvironmentConfig>): ConfigValidationResult {
|
||||
this.config = { ...this.config, ...updates };
|
||||
return this.validateConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为默认配置
|
||||
*/
|
||||
resetToDefaults(): void {
|
||||
this.config = this.loadConfiguration();
|
||||
console.log('🔄 端口配置已重置为默认值');
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出配置
|
||||
*/
|
||||
exportConfig(): string {
|
||||
const configLines = [
|
||||
'# 智能端口管理配置',
|
||||
`VITE_PORT_STRATEGY=${this.config.strategy}`,
|
||||
`VITE_BASE_PORT=${this.config.basePort}`,
|
||||
`VITE_PORT_RANGE_START=${this.config.portRangeStart}`,
|
||||
`VITE_PORT_RANGE_END=${this.config.portRangeEnd}`,
|
||||
`VITE_TENANT_PORT_OFFSET=${this.config.tenantPortOffset}`,
|
||||
`VITE_ENVIRONMENT_PORT_OFFSET=${this.config.environmentPortOffset}`,
|
||||
`VITE_PORT_AUTO_DETECT=${this.config.autoDetect}`,
|
||||
`VITE_PORT_STRICT_MODE=${this.config.strictMode}`,
|
||||
`VITE_PORT_CACHE_ENABLED=${this.config.cacheEnabled}`,
|
||||
`VITE_PORT_CACHE_EXPIRY=${this.config.cacheExpiry}`,
|
||||
'',
|
||||
'# 开发服务器配置',
|
||||
`VITE_DEV_HOST=${this.config.devHost}`,
|
||||
`VITE_DEV_OPEN_BROWSER=${this.config.openBrowser}`,
|
||||
`VITE_DEV_CORS_ENABLED=${this.config.corsEnabled}`,
|
||||
`VITE_DEV_HTTPS_ENABLED=${this.config.httpsEnabled}`
|
||||
];
|
||||
|
||||
return configLines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置摘要
|
||||
*/
|
||||
getConfigSummary(): {
|
||||
environment: Environment;
|
||||
strategy: string;
|
||||
portRange: string;
|
||||
features: string[];
|
||||
status: 'healthy' | 'warning' | 'error';
|
||||
} {
|
||||
const validation = this.validateConfiguration();
|
||||
const features: string[] = [];
|
||||
|
||||
if (this.config.autoDetect) features.push('自动检测');
|
||||
if (this.config.cacheEnabled) features.push('缓存启用');
|
||||
if (this.config.strictMode) features.push('严格模式');
|
||||
if (this.config.httpsEnabled) features.push('HTTPS');
|
||||
if (this.config.corsEnabled) features.push('CORS');
|
||||
|
||||
let status: 'healthy' | 'warning' | 'error' = 'healthy';
|
||||
if (validation.errors.length > 0) {
|
||||
status = 'error';
|
||||
} else if (validation.warnings.length > 0) {
|
||||
status = 'warning';
|
||||
}
|
||||
|
||||
return {
|
||||
environment: this.environment,
|
||||
strategy: this.config.strategy,
|
||||
portRange: `${this.config.portRangeStart}-${this.config.portRangeEnd}`,
|
||||
features,
|
||||
status
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 导出默认实例
|
||||
export const portConfigManager = new PortConfigManager();
|
||||
Reference in New Issue
Block a user