问题描述
业务服务自动注册到xxl-job后通过管理后台看到,注册的ip是容器ip,xxl-job和业务服务部署在不同服务器上,通过容器ip调用必然失败
解决思路
想办法让业务服务自动注册的ip,为宿主机ip,而不是现在的容器ip
排查过程
1,对比查看多个执行器
发现同一个执行器,业务服务部署了2个节点,有一个节点是容器ip,有一个是正确的宿主机ip,问题比想象棘手,并非业务服务获取ip问题,应该和环境有关
查看了业务服务启动docker compose 脚本都是host模式,理论上应该取的都是宿主机ip,继续对比环境
对比了好几个业务服务节点,真相了,注册后能拿到宿主机ip的只有这个ubuntu系统服务器,其它centos系统服务器的都获取不到宿主机ip
3,查看xxl-job客户端源码找出获取ip的方式
com.xxl.job.core.executor.XxlJobExecutor
private void initEmbedServer(String address, String ip, int port, String appname, String accessToken) throws Exception {
// fill ip port
port = port>0?port: NetUtil.findAvailablePort(9999);
ip = (ip!=null&&ip.trim().length()>0)?ip: IpUtil.getIp();
// generate address
if (address==null || address.trim().length()==0) {
String ip_port_address = IpUtil.getIpPort(ip, port); // registry-address:default use address to registry , otherwise use ip:port if address is null
address = "http://{ip_port}/".replace("{ip_port}", ip_port_address);
}
// accessToken
if (accessToken==null || accessToken.trim().length()==0) {
logger.warn(">>>>>>>>>>> xxl-job accessToken is empty. To ensure system security, please set the accessToken.");
}
// start
embedServer = new EmbedServer();
embedServer.start(address, port, appname, accessToken);
}
如果有配置ip时就去配置ip,如果没有就通过
IpUtil.getIp()获取,这里在centos系统获取的时候拿到的是容器ip,最终通过java.net.InetAddress.getLocalHost()获取,没有继续往下纠察
4,尝试服务器命令获取ip
hostname -i
# centos返回
hostname: Name or service not known
# ubuntu返回
172.17.185.134 172.26.0.1 172.65.0.1 192.168.80.1
很明显centos无法正确获取到ip
问题总结
centos 系统下docker部署的业务服务(定时任务执行端)无法正确获取宿主机ip
解决
手动设置
xxl-job.executor的ip为宿主机ip,需要注意多节点部署,ip取值不能写静态,得跟着环境变化,所以可以将宿主机ip写入环境变量中。
1,添加宿主机ip到环境变量
XXL_JOB_CLIENT_IP=127.6.8.9
2,业务服务手动配置xxl-job.executor.ip,值取环境变量的宿主机ip
xxl:
job:
executor:
ip: ${XXL_JOB_CLIENT_IP}