Files
DDDMicroFrontend/docker/traefik/nacos-watcher.js

133 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const axios = require('axios');
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
// 配置
const NACOS_SERVER = 'http://192.168.31.101:8848'; // 你的 Nacos 地址
const NAMESPACE = 'public';
const SERVICES = ['main-app', 'app-product', 'app-shared']; // 三个模块的服务名
const TRAEFIK_DYNAMIC_CONFIG = path.join(__dirname, './dynamic.yml');
const CHECK_INTERVAL = 5000; // 10秒检查一次服务变化
console.log('配置文件路径:', TRAEFIK_DYNAMIC_CONFIG);
if (!TRAEFIK_DYNAMIC_CONFIG) {
throw new Error('配置文件路径生成失败,路径为空');
}
// 通用中间件配置(可根据服务特性调整)
const commonMiddlewares = {
// 限流中间件(独立配置,关键修复)
rateLimit: {
rateLimit: {
average: 100,
burst: 200,
period: '1s',
sourceCriterion: {
ipStrategy: {depth: 2}
}
}
},
// 压缩中间件
compress: {
compress: {
excludedContentTypes: ['text/event-stream'],
minResponseBodyBytes: 1024
}
},
// IP白名单中间件示例允许本地和192.168.31网段)
ipWhiteList: {
ipWhiteList: {
sourceRange: ['127.0.0.1/32', '192.168.31.0/24']
}
},
// // 重定向中间件HTTP→HTTPS
// redirectToHttps: {
// redirectScheme: {
// scheme: 'https',
// permanent: true
// }
// },
// 重试中间件(关键修复:将重试配置移到这里)
retries: {
retry: {
attempts: 3,
initialInterval: '200ms'
}
}
};
// 从 Nacos 获取服务实例
async function getServiceInstances(serviceName) {
try {
const res = await axios.get(`${NACOS_SERVER}/nacos/v1/ns/instance/list`, {
params: {serviceName, namespaceId: NAMESPACE},
});
return res.data.hosts || [];
} catch (err) {
console.error(`获取 ${serviceName} 实例失败:`, err.message);
return [];
}
}
// 生成 traefik 动态配置
async function generateTraefikConfig() {
const config = {
http: {
routers: {},
services: {},
middlewares: commonMiddlewares
}
};
for (const serviceName of SERVICES) {
const instances = await getServiceInstances(serviceName);
if (instances.length === 0) {
console.warn(`服务 ${serviceName} 无可用实例`);
continue;
}
// 1. 配置服务(服务名 + 实例列表)
config.http.services[`${serviceName}-service`] = {
loadBalancer: {
servers: instances.map(inst => ({
url: `http://${inst.ip}:${inst.port}`,
})),
// 熔断配置
// healthCheck: {
// path: '/health', // 假设服务有健康检查接口
// interval: '30s',
// timeout: '5s',
// unhealthyThreshold: 3,
// healthyThreshold: 2
// }
}
};
// 2. 配置路由(路径前缀 + 绑定服务)
config.http.routers[`${serviceName}-router`] = {
rule: `PathPrefix(\`/${serviceName}\`)`, // 如 /main、/product
service: `${serviceName}-service`,
entryPoints: ['web'],
// 应用中间件压缩、IP白名单、限流、重试等
middlewares: ['compress', 'ipWhiteList', 'rateLimit', 'retries'],
};
}
// 将对象转换为 YAML 字符串
const yamlString = yaml.dump(config, {
indent: 2, // 缩进空格数
skipInvalid: true, // 跳过无效类型
noRefs: true // 禁止引用(防止循环引用问题)
});
console.log("yamlString: ", yamlString)
// 写入动态配置文件
fs.writeFileSync(TRAEFIK_DYNAMIC_CONFIG, yamlString, "utf8");
console.log('动态配置已更新');
}
// 定时检查并更新配置
setInterval(generateTraefikConfig, CHECK_INTERVAL);
// 立即执行一次
generateTraefikConfig();