xxl-job 执行器在 host 网络模式下注册到错误 IP 的问题与解决方案
xxl-job 执行器在 host 网络模式下注册到错误 IP 的问题与解决方案
背景与现象
- 容器采用
network_mode: host
运行,但 xxl-job 执行器在“自动注册机器地址”时经常注册到 Docker 桥接网卡 IP(如172.168.18.1
),而非宿主主网卡 IP(如10.12.11.22
)。 - 即便 JVM 参数加入
-Dxxl.job.executor.ip=10.12.11.22
,页面仍可能出现错误地址,或被配置中心覆盖。
根因分析
- 执行器“自动探测网卡”在多网卡环境下不稳定,容易拾取
br-*
/docker0
等网卡。 - 配置中心(Nacos)若下发了空的
xxl.job.executor.address
或指定了与期望不一致的ip
,会覆盖 JVM 参数,使执行器回退到“自动探测”或注册为不期望的 IP。 - 管理端若残留历史错误注册记录,即使修正配置,页面仍会显示旧节点,造成“看起来未生效”。
最终解决方案(采用 Nacos 变量 + Compose 注入)
- 通过 Nacos 配置使用 Spring 占位符读取容器环境变量,动态注入执行器的 IP/端口。
- 在 docker-compose 中通过
.env
或直接环境变量提供HOST_IP
(宿主机主网卡 IP)。 - Jenkins 部署阶段将
HOST_IP
写入.env
,Compose 自动注入到容器环境。
配置清单
1) Nacos 配置(顶层 YAML,不要缩进到其他模块下)
- 仅使用 ip+port:
xxl:job:admin:addresses: http://10.12.11.26:18080/xxl-job-adminaccessToken:executor:appname: auth-webaddress:ip: ${XXL_JOB_EXECUTOR_IP:${HOST_IP:}} # 先取 XXL_JOB_EXECUTOR_IP,缺省用 HOST_IP,最后允许空port: ${XXL_JOB_EXECUTOR_PORT:9997} # 未提供则默认 9997logpath: log/xxl-job/jobhandlerlogretentiondays: 30
注意:
- 绝对不要保留空的
address:
键(空值也会覆盖,导致回退自动探测)。 - 如希望“强制注册地址”(优先级最高),可改用:
xxl:job:admin:addresses: http://10.12.11.26:18080/xxl-job-adminexecutor:appname: auth-webaddress: ${XXL_JOB_EXECUTOR_ADDRESS:} # 直接传 http://10.12.11.22:9997port: ${XXL_JOB_EXECUTOR_PORT:9997}
2) docker-compose.yml(服务段)
services:newsms-prd:image: x454262h22.qicp.vip:86/bbgu/newsms:prd-35container_name: auth-webnetwork_mode: hostvolumes:- "./log/:/usr/app/log"environment:- SPRING_PROFILES_ACTIVE=prd-bbgu- XXL_JOB_EXECUTOR_IP=${HOST_IP} # Nacos 将解析此变量# - XXL_JOB_EXECUTOR_PORT=9997 # 如需覆盖默认端口则开启
提示:
network_mode: host
下ports:
映射无效但不影响运行;确保执行器端口实际监听正确(如 9997)。
3) Jenkinsfile(部署阶段片段)
- 固定写入宿主机 IP 到远端
.env
,Compose 自动读取:
// 直接写入固定的 HOST_IP
sh 'ssh root@10.12.11.22 "cd /files/jw_app/backend/' + appName + ' && echo HOST_IP=10.12.11.22 > .env && cat .env"'
sh 'ssh root@10.12.11.22 "cd /files/jw_app/backend/' + appName + ' && docker compose down || true"'
sh 'ssh root@10.12.11.22 "cd /files/jw_app/backend/' + appName + ' && docker compose up -d --remove-orphans"'
可替换为动态获取 HOST_IP(按需):
HOST_IP=$(ip -4 route get 1.1.1.1 | awk '{print $7; exit}')
并写入 .env
。
操作步骤
- 修改 Nacos 配置为上述占位符写法,确保没有空的
address:
键(或明确写 address 为正确 URL)。 - 在 Jenkins 部署阶段将
HOST_IP
写入远端/files/jw_app/backend/<appName>/.env
。 docker compose up -d
启动容器。- 清理 xxl-job-admin 历史错误注册节点(或执行 SQL 清理
xxl_job_registry
对应记录)。 - 重启执行器容器后,查看“在线机器”是否为
http://10.12.11.22:9997/
。
验证
- 宿主机检查端口监听:
ss -ltnp | grep 9997 || netstat -ltnp | grep 9997
- 容器日志确认已读取环境变量:
docker compose logs -f | grep -E "XXL_JOB_EXECUTOR|xxl"
- 容器内查看进程参数与环境:
docker exec -it auth-web env | grep XXL
docker exec -it auth-web ps -ef | grep java
- xxl-job-admin 页面“在线机器”应显示:
http://10.12.11.22:9997/
。
常见坑与规避
- 空键覆盖:Nacos 中
address:
或ip:
即使无值也会覆盖 JVM/环境变量,导致回退自动探测。 - 嵌套层级错误:
xxl:
必须是 YAML 顶层(与spring:
同级),避免缩进到其他模块下。 - 旧注册未清理:admin 页面会持续显示旧节点,需手动删除或清库后再观察。
- 多网卡环境:如必须自动探测,建议代码或启动脚本基于默认路由计算主 IP,而非遍历网卡。
备选方案(不依赖配置中心)
- 强制注册地址(优先级最高):
- JVM:
-Dxxl.job.executor.address=http://10.12.11.22:9997
- Nacos 中不要下发
address:
空键或冲突键
- JVM:
- 在 admin 将执行器注册方式改为“手动录入”,直接填
http://10.12.11.22:9997
;完全绕过自动注册与网卡选择。
结果
- 采用 Nacos 占位符 + Compose 注入
HOST_IP
,执行器稳定注册为宿主主网卡地址。 - Jenkins 自动写入
.env
保证环境变量准确,不需频繁改镜像或手动维护。