feat(port): 实现智能端口管理系统

- 新增端口管理器类,支持端口分配、验证和缓存管理
- 实现环境优先级策略,根据环境自动选择合适的端口范围
- 集成租户识别系统,为每个租户分配独立端口
- 添加端口分配结果统计和历史记录查询功能
- 优化端口缓存机制,自动清理过期绑定
This commit is contained in:
2025-09-03 18:52:39 +08:00
parent 8c75b5d349
commit 7052ccce61
33 changed files with 6704 additions and 38 deletions

View 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();