使用的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)的问题的问题啦!