xxl-job 客户端部署docker自动注册ip为容器ip导致调用失败

1,731 阅读2分钟

问题描述

image.png

业务服务自动注册到xxl-job后通过管理后台看到,注册的ip是容器ip,xxl-job和业务服务部署在不同服务器上,通过容器ip调用必然失败

解决思路

想办法让业务服务自动注册的ip,为宿主机ip,而不是现在的容器ip

排查过程

1,对比查看多个执行器

image.png

发现同一个执行器,业务服务部署了2个节点,有一个节点是容器ip,有一个是正确的宿主机ip,问题比想象棘手,并非业务服务获取ip问题,应该和环境有关

image.png

查看了业务服务启动docker compose 脚本都是host模式,理论上应该取的都是宿主机ip,继续对比环境

image.png

对比了好几个业务服务节点,真相了,注册后能拿到宿主机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}