热爱技术,追求卓越
不断求索,精益求精

使用groovy解决elasticjob抛出HostException(ip is null)的问题

使用的elasticjob版本为3.0.1

<dependency>
    <groupId>org.apache.shardingsphere.elasticjob</groupId>
    <artifactId>elasticjob-lite-spring-boot-starter</artifactId>
    <version>3.0.1</version>
</dependency>

编写好job代码后在linux环境能正常运行,但个人开发的笔记本上抛出HostException,异常信息为ip is null,异常情况如下:

org.apache.shardingsphere.elasticjob.infra.env.HostException: ip is null
    at org.apache.shardingsphere.elasticjob.infra.env.IpUtils.getIp(IpUtils.java:70) ~[elasticjob-infra-common-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.infra.handler.sharding.JobInstance.<init>(JobInstance.java:44) ~[elasticjob-infra-common-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.registerStartUpInfo(JobScheduler.java:176) ~[elasticjob-lite-core-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.createJobScheduleController(JobScheduler.java:140) ~[elasticjob-lite-core-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.<init>(JobScheduler.java:90) ~[elasticjob-lite-core-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap.<init>(ScheduleJobBootstrap.java:36) ~[elasticjob-lite-core-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.registerClassedJob(ElasticJobBootstrapConfiguration.java:108) ~[elasticjob-lite-spring-boot-starter-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.constructJobBootstraps(ElasticJobBootstrapConfiguration.java:91) ~[elasticjob-lite-spring-boot-starter-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.createJobBootstrapBeans(ElasticJobBootstrapConfiguration.java:64) ~[elasticjob-lite-spring-boot-starter-3.0.1.jar:3.0.1]
    at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.afterSingletonsInstantiated(ElasticJobBootstrapConfiguration.java:52) ~[elasticjob-lite-spring-boot-starter-3.0.1.jar:3.0.1]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:963) ~[spring-beans-5.3.12.jar:5.3.12]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.12.jar:5.3.12]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.12.jar:5.3.12]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.6.jar:2.5.6]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.5.6.jar:2.5.6]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) [spring-boot-2.5.6.jar:2.5.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) [spring-boot-2.5.6.jar:2.5.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) [spring-boot-2.5.6.jar:2.5.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) [spring-boot-2.5.6.jar:2.5.6]

查看org.apache.shardingsphere.elasticjob.infra.env.IpUtils类,getIp方法如下。

 /**
 * Get IP address for localhost.
 * 
 * @return IP address for localhost
 */
public static String getIp() {
    if (null != cachedIpAddress) {
        return cachedIpAddress;
    }
    NetworkInterface networkInterface = findNetworkInterface();
    if (null != networkInterface) {
        Enumeration<InetAddress> ipAddresses = networkInterface.getInetAddresses();
        while (ipAddresses.hasMoreElements()) {
            InetAddress ipAddress = ipAddresses.nextElement();
            if (isValidAddress(ipAddress) && isPreferredAddress(ipAddress)) {
                cachedIpAddress = ipAddress.getHostAddress();
                return cachedIpAddress;
            }
        }
    }
    throw new HostException("ip is null");
}

想巧妙利用cachedIpAddress,当cachedIpAddress非空时返回值就是cachedIpAddress。

private static volatile String cachedIpAddress;

但cachedIpAddress的定义是私有的,这让我想到了万能的groovy,引入依赖:

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.4.15</version>
</dependency>

编写如下方法,目的只是为了在特殊情况下改变cachedIpAddress的值。

/**
 * 屏蔽org.apache.shardingsphere.elasticjob.infra.env.IpUtils.getIp()抛出
 * HostException(ip is null) 的异常导致windows本地程序无法启动
 */
private static void shieldElasticjobIpIsNull(){
    try {
        IpUtils.getIp();
    } catch (HostException e) {
        //抛出HostException 且 异常信息为 "ip is null" 时,设置ip地址为 0.0.0.0
        if("ip is null".equals(e.getMessage())){
            String code = "org.apache.shardingsphere.elasticjob.infra.env.IpUtils.cachedIpAddress=\"0.0.0.0\";";
            GroovyShell groovy = new GroovyShell();
            groovy.evaluate(code);
        }
    }
}

由于我们是spring boot应用,所以在启动类的main方法内部一开始就调用上面这个shieldElasticjobIpIsNull初始化cachedIpAddress:

public static void main(String[] args) {
    //屏蔽org.apache.shardingsphere.elasticjob.infra.env.IpUtils.getIp()抛出
    //HostException(ip is null) 的异常导致windowes本地程序无法启动的问题
    shieldElasticjobIpIsNull();
    //启动springboot
    SpringApplication.run(Application.class, args);
}

现在不管什么地方启动应用,都不用担心HostException(ip is null)的问题的问题啦!

赞(2)
未经允许不得转载:LoveCTO » 使用groovy解决elasticjob抛出HostException(ip is null)的问题

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

热爱技术 追求卓越 精益求精