实现 nacos + traefik,改了很多东西!!!
This commit is contained in:
24
docker/traefik/docker-compose.yml
Normal file
24
docker/traefik/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.0
|
||||
container_name: traefik
|
||||
network_mode: "host" # 主机网络模式
|
||||
volumes:
|
||||
- ./traefik.yml:/etc/traefik/traefik.yml
|
||||
- ./dynamic.yml:/etc/traefik/dynamic.yml # 动态配置文件
|
||||
restart: always
|
||||
|
||||
# 2. Nacos 服务监听脚本
|
||||
nacos-watcher:
|
||||
user: "root"
|
||||
privileged: true
|
||||
image: node:24.8.0-alpine3.21
|
||||
container_name: nacos-watcher
|
||||
network_mode: "host"
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./:/app # 挂载当前目录到容器
|
||||
command: sh -c "npm install && node nacos-watcher.js"
|
||||
restart: always
|
||||
68
docker/traefik/dynamic.yml
Normal file
68
docker/traefik/dynamic.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
http:
|
||||
routers:
|
||||
main-app-router:
|
||||
rule: PathPrefix(`/main-app`)
|
||||
service: main-app-service
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- compress
|
||||
- ipWhiteList
|
||||
- rateLimit
|
||||
- retries
|
||||
app-product-router:
|
||||
rule: PathPrefix(`/app-product`)
|
||||
service: app-product-service
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- compress
|
||||
- ipWhiteList
|
||||
- rateLimit
|
||||
- retries
|
||||
app-shared-router:
|
||||
rule: PathPrefix(`/app-shared`)
|
||||
service: app-shared-service
|
||||
entryPoints:
|
||||
- web
|
||||
middlewares:
|
||||
- compress
|
||||
- ipWhiteList
|
||||
- rateLimit
|
||||
- retries
|
||||
services:
|
||||
main-app-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://192.168.31.101:1300
|
||||
app-product-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://192.168.31.101:1301
|
||||
app-shared-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://192.168.31.101:1333
|
||||
middlewares:
|
||||
rateLimit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 200
|
||||
period: 1s
|
||||
sourceCriterion:
|
||||
ipStrategy:
|
||||
depth: 2
|
||||
compress:
|
||||
compress:
|
||||
excludedContentTypes:
|
||||
- text/event-stream
|
||||
minResponseBodyBytes: 1024
|
||||
ipWhiteList:
|
||||
ipWhiteList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.31.0/24
|
||||
retries:
|
||||
retry:
|
||||
attempts: 3
|
||||
initialInterval: 200ms
|
||||
133
docker/traefik/nacos-watcher.js
Normal file
133
docker/traefik/nacos-watcher.js
Normal file
@@ -0,0 +1,133 @@
|
||||
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();
|
||||
15
docker/traefik/package.json
Normal file
15
docker/traefik/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "traefik",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.8",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
16
docker/traefik/traefik.yml
Normal file
16
docker/traefik/traefik.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
# 启用 Dashboard
|
||||
api:
|
||||
dashboard: true
|
||||
insecure: true # 开发环境允许HTTP访问
|
||||
|
||||
# 入口点配置
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80" # 监听80端口,Web 流量
|
||||
|
||||
# 服务发现与配置源(关键:子项缩进必须一致)
|
||||
providers:
|
||||
# 动态路由规则文件
|
||||
file:
|
||||
filename: "/etc/traefik/dynamic.yml"
|
||||
watch: true # 自动监听文件变化
|
||||
Reference in New Issue
Block a user