前言
spring自带的定时任务,能解决很多问题。在当前公司的项目模块中,我使用了这一功能。然而因为服务器配置不当,引发了任务重复执行。困扰我多日。
问题
公司当前业务中涉及到统计模块。该模式我使用了spring的定时任务。其中一个任务每日的凌晨4点执行一次。但是结果发现执行了2次,产生2条记录。
原因
寻找原因的时候,基本都是 通过搜索引擎,很幸运,不是我一个人遇到,大家都遇到类似的问题。
阅读几篇文章分析之后,得出的结论如下:
tomcat的服务器配置不当,导致项目被加载了2次,从而引发同一个定时任务变成2个。
具体什么样子的配置会导致项目加载2次呢。
主要是tomcat的server.xml中 host和context参数。
出现问题时的配置如下:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="D:\Program Files\apache-tomcat-8.5.23\webapps\lightai-api" path="/" reloadable="true" />
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="api.lightai.insigma.com_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
tomcat 会自动加载webapps下文件夹作为项目。访问路径为 localhost:8080/项目文件夹名
如果配置了context,则tomcat 会加载一次context的文件夹作为默认项目。
最终导致 D:\Program Files\apache-tomcat-8.5.23\webapps\lightai-api 被2次加载,问题出现。
而当初原本配置context是为了实现访问 localhost:8080 这样访问项目,由于不熟悉这一加载机
制,引发了这个故障。
解决
- 解决方法一:修改配置server.xml配置,去掉context配置。
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="api.lightai.insigma.com_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
如果需要在美化项目的访问路径,可以通过nginx来实现。
- 解决方法二:将context的配置中文件夹移动到webapps外部。避免重复加载。
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context docBase="新的项目路径,不位于webapps目录下" path="/" reloadable="true" />
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="api.lightai.insigma.com_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
当前我使用的第一种方案。