const config = require("../config") const http = require("../http") const yaml = require("js-yaml"); const path = require('path'); const fs = require('fs'); class Utils { // 存储 Nacos上 服务列表 的服务名称 ServiceNameList = [] constructor() { this.getServiceName() } /** * 获取Nacos上的服务名称数组 * @returns {Promise} */ async getServiceName() { console.log("1: [getServiceName] 从Nacos 获取服务名..") const {doms} = await http.get({ url: config.nacosApi.apiList.serviceList, data: {pageNo: 1, pageSize: 20}, }); if (doms.length === 0) { throw new Error("No service found for service list"); } this.serviceName = doms; console.log("2: [getServiceName] 服务名为:", this.serviceName) await this.generateTraefikConfig() } /** * 从 Nacos 获取服务实例 * @param serviceName * @returns {Promise<*|*[]>} */ async getServiceInstances(serviceName) { const {hosts} = await http.get({ url: config.nacosApi.apiList.instanceInfo, data: {serviceName, namespaceId: config.nacosConfig.nameSpace}, }); return hosts || [] } /** * 生成 traefik 动态配置 * @returns {Promise} */ async generateTraefikConfig() { const traefikConf = { http: { routers: {}, services: {}, middlewares: config.traefikConfig.middlewaresConfig, } }; for (const serviceName of this.serviceName) { const instances = await this.getServiceInstances(serviceName); if (instances.length === 0) { console.warn(`服务 ${serviceName} 无可用实例`); continue; } // 1. 配置服务(服务名 + 实例列表) traefikConf.http.services[`${serviceName}-service`] = { loadBalancer: { servers: instances.map(inst => ({ url: `http://${inst.ip}:${inst.port}`, })), } }; // 2. 配置路由(路径前缀 + 绑定服务) traefikConf.http.routers[`${serviceName}-router`] = { rule: `PathPrefix(\`/${serviceName}\`)`, // 如 /main、/product service: `${serviceName}-service`, entryPoints: ['web'], // 应用中间件(压缩、IP白名单、限流、重试等) middlewares: config.traefikConfig.middlewaresStr, }; } this.stringToYaml(traefikConf) } /** * 生成 yaml 配置文件 * @param conf */ stringToYaml(conf) { console.log("3: [stringToYaml] 生成配置:", JSON.stringify(conf, null, 2)); console.log() console.log() const yamlString = yaml.dump(conf, { indent: 2, // 缩进空格数 skipInvalid: true, // 跳过无效类型 noRefs: true // 禁止引用(防止循环引用问题) }); fs.writeFileSync(config.filePath, yamlString, "utf8"); } } module.exports = Utils