springboot 定时任务部署至linux服务器上后会执行两次问题(以下分为两种原因)
springboot定时任务在本地运行时,正常执行且只执行一次,但是在maven打包成war包,部署至linux服务器上之后,定时任务奇怪的执行了两次。
由于未做负载均衡,所以可以先排除是因为多台服务器都运行此代码导致。
一、
参考了网上的一些资料后了解到,是因为定时任务被实例化了两次的缘故,这个现象归根到底问题出在tomcat的service.xml的配置上。
在service.xml中知道如下代码:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> <Context docBase="emall" path="/" reloadable="true" /> </Host>
由于配置了appBase="webapps"和docBase="emall",原因是tomcat加载完appBase="webapps"之后又去加载docBase,因此造成加载两次项目的问题。
解决办法:
将 appBase="webapps"改成appBase="",将docBase="emall" 改成项目的绝对路径docBase="/usr/local/src/tomcat-emall/webapps/emall" ,这样,在tomcat启动后只会去加载一次docBase,重启tomcat,问题解决!!
参考:https://blog.csdn.net/yaobengen/article/details/70312663
后来发现了因为这样的配置出现的一下现象:
如果在webapps文件夹中没有emall项目文件夹(非压缩包),则在启动服务的时候会在tomcat根目录下生成一个ROOT的文件夹,里面则是emall项目的源文件。
如果在webapps文件夹下已经存在emall项目文件夹,则在启动服务的时候不会生成上述的ROOT文件夹,项目的源文件会在此emall文件夹下。
关于appBase与docBase的区别与联系,可以参考https://blog.csdn.net/chenxiaodan_danny/article/details/45397765
二、
以上原因如果无效的话,可参照以下情况:
项目打war包,pom中屏蔽掉springboot内置的tomcat
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
@SpringBootApplication @EnableScheduling @EnableSwagger2 //public class MyyWaterinfoApplication extends SpringBootServletInitializer implements CommandLineRunner { public class MyyWaterinfoApplication { public static void main(String[] args) { SpringApplication.run(MyyWaterinfoApplication.class, args); } // 需要把web项目打成war包部署到外部tomcat运行时需要改变启动方式 // @Override // protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { // this.setRegisterErrorPageFilter(false); // return builder.sources(MyyWaterinfoApplication.class); // } // springboot运行后此方法首先被调用 // 实现CommandLineRunner抽象类中的run方法 // @Override // public void run(String... args) throws Exception { // System.out.println("Report time for you: " + new Date().toString() + " ---> darling~ yours springboot2.0 project has been successfully started!nice day,right?"); // }