spring Scheduled多次执行问题 线上Case已解决
需求:对VIP即将到期的用户发送邮件通知,每天的9点半,17点半,22点执行一次
项目:springboot + tomcat
这里面涉及两个问题
第一:tomcat配置问题。
有很多公司可能会有多个项目部署在一个tomcat下面,例如两个域名service.xxx.com和manage.xxx.com都部署在tomcat下面。
我原来的tomcat/config/server.conf host部分配置文件是这样的,
<Host name="manage.XXX.cn" appBase=""
unpackWARs="true" autoDeploy="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="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="" docBase="D:\apache-tomcat-9.0.0.M10\webapps\manage.XXX.cn" reloadable="true"></Context>
</Host>
<Host name="service.XXX.cn" appBase=""
unpackWARs="true" autoDeploy="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="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="" docBase="D:\apache-tomcat-9.0.0.M10\webapps\service.XXX.cn" reloadable="true"></Context>
</Host>
原配置会导致项目被加载两次,由于本人技术有限,还不清楚tomcat的加载机制,以后会去深入学习。
但是查看了tomcat的官方文档:
path: Even when statically defining a Context in server.xml, this attribute must not be set unless either the docBase is not located
under the Host’s appBase or both deployOnStartup and autoDeploy are false. If this rule is not followed, double deployment is likely to result.假如docBase的目录已经在appBase配置的目录下,或者deployOnStartup与autoDeploy都为false,就不需要配置path属性。如果配置了,就极有可能导致双重部署的结果。
修改后:
<Host name="manage.XXX.cn" appBase=""
unpackWARs="true" autoDeploy="false" deployOnStartup="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="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="" docBase="D:\apache-tomcat-9.0.0.M10\webapps\manage.XXX.cn" reloadable="true"></Context>
</Host>
<Host name="service.XXX.cn" appBase=""
unpackWARs="true" autoDeploy="false" deployOnStartup="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="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="" docBase="D:\apache-tomcat-9.0.0.M10\webapps\service.XXX.cn" reloadable="true"></Context>
</Host>
第二:Scheduled cron表达式语法不熟悉,入坑了
我原来cron表达式的写法:@Scheduled(cron = “0 30,30,0 9,17,22 * * ?”)
我本以为这样会是每天9点半,17点半,22点执行一次,但实际上是9点,9点半,17点,17点半,22点,22点半各执行了一次。这里就是因为对语法不够了解,入了坑。
我的解决方法可能有点笨,就是写了三个Scheduled
@Scheduled(cron = “0 30 9 * * ?”)
@Scheduled(cron = “0 30 17 * * ?”)
@Scheduled(cron = “0 0 22 * * ?”)
推荐一个在线Cron表达式解析网址:http://cron.qqe2.com/