本文介紹如何將任務調度應用優雅下線。
背景資訊
在實際業務情境下,定時任務持續地按固定頻率在應用進程中執行。當應用在發布重啟時,進程需暫時下線。如果直接關閉應用,進行中中的定時任務將被中斷,可能導致資料不完整或其他問題。為避免該情況,SchedulerX實現了定時任務的優雅下線功能,在關閉應用前,需等待當前進行中的任務執行完成後,然後再安全地關閉應用。
使用限制
用戶端版本為1.10.8及以上。
優雅下線示意

如何配置
當前 SchedulerX 可同時支援單機任務、分布式任務多種執行模式下的優雅下線能力。另外,離線定時任務不同於即時線上業務情境,可能存在執行長耗時的特性,但是應用進程在停機時不會無限等待。您可以通過以下配置運行中的任務應用延遲停機的時間。
#優雅下線模式,WAIT_ALL:等待全部; WAIT_RUNNING:等待運行中。
#該參數不配置則不啟用優雅下線功能(預設不開啟優雅下線)。
spring.schedulerx2.graceShutdownMode=WAIT_ALL
#優雅下線等待逾時時間長度(單位:秒),預設無逾時。
spring.schedulerx2.graceShutdownTimeout=10
#是否開啟http服務介面,預設false。
spring.schedulerx2.httpServerEnable=true
#http下線介面連接埠,預設51886。
spring.schedulerx2.httpServerPort=52333下線模式 | 描述 |
等待全部( | (推薦)該模式下,待所有已接收的任務和子任務執行完成後,應用才退出。 |
等待運行中( | 該模式下,應用在退出時,將等待已指派線程並在處理中的任務或子任務執行完成,隊列中的任務將被放棄執行。 |
下線實現方式
為了方便業務應用整合在各種部署形態下的發布流程,您可以使用以下幾種方式實現優雅停機。
方式一:通過kill -15優雅停止
SchedulerX SDK 添加了JVM進程關閉時的鉤子函數,實現了程式優雅退出的功能。使用者在停止應用進程時可以採用kill -15 進程ID的方式停止應用進程,運行中的應用進程將按照對應的配置策略完成任務執行後的優雅退出。
執行下線指令碼停止業務應用時,不能直接採用kill -9,否則該能力將失效。部分業務應用下線的指令碼先採用kill -15,監測並等待一段時間後,再執行kill -9命令強制停止。建議根據應用任務的特徵來合理設定下線等待的時間,防止發布過程過慢。
方式二:通過SpringBoot shutdown事件停止
如果通過 SpringBoot 方式初始化接入 SchedulerX,可以相容SpringBoot 提供的actuator功能來實現優雅下線,它能在響應 Spring 容器關閉事件時進行定時任務的優雅下線處理。
開啟SpringBoot actuator步驟如下:
在應用程式的
pom.xml檔案中添加依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>配置開啟shutdown介面。
management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown執行下線。
curl -X GET http://NodeIP:Port/actuator/shutdown方式三:通過HTTP介面停止
通過配置項在當前業務的應用進程中開啟一個HTTP介面服務,用於外部自訂請求實現當前應用進程中的定時任務優雅下線處理。應用參數配置如下:
#是否開啟http服務介面,預設false。
spring.schedulerx2.httpServerEnable=true
#http下線介面連接埠,預設51886。
spring.schedulerx2.httpServerPort=51886調用如下HTTP介面即可實現任務調度服務的優雅下線
curl -X GET http://NodeIP:51886/schedulerx/worker/shutdown運用整合方案
通常需要將對應的優雅下線能力整合到日常發布的營運流程中,以規避應用重啟時出現的定時任務業務有損。以下將介紹幾種常見的整合形式。
方案一:自建部署流程整合
通常在自建CD流程中會有一個應用進程停止的節點,該節點可通過構建一個stop.sh指令碼用於應用進程的停止退出。指令碼內容需包含應用優雅下線的相關邏輯處理,可採用上述章節下線實現方式的任意一種方式即可。
自建CD流程如圖所示:

停止應用進程的指令碼案例:
#應用啟用成功後進程ID資訊會寫入app.pid檔案
PID="{應用部署路徑}/app.pid"
FORCE=1
if [ -f ${PID} ]; then
TARGET_PID=`cat ${PID}`
kill -15 ${TARGET_PID}
loop=1
while(( $loop<=5 ))
do
#health 檢查當前應用進程確實已經結束,可根據應用特徵自訂
health
if [ $? == 0 ]; then
echo "check $loop times, current app has not stop yet."
sleep 5s
let "loop++"
else
FORCE=0
break
fi
done
if [ $FORCE -eq 1 ]; then
echo "App(pid:${TARGET_PID}) stop timeout, forced termination."
kill -9 ${TARGET_PID}
if
rm -rf ${PID}
echo "App(pid:${TARGET_PID}) stopped successful."
fi方案二:K8s容器化部署PreStop方式
利用K8s Pod生命週期中銷毀時的preStop事件處理來觸發應用的優雅下線,同時preStop hook可通過exec執行指令碼和HTTP請求方式來實現優雅下線邏輯處理。
Exec指令碼方式:直接通過停止應用進程,或者調用提前預設的
stop.sh指令碼實現應用進程退出。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app-image:latest
lifecycle:
preStop:
exec:
# command: ["/bin/sh", "-c", "kill -15 PID && sleep 30"]
command: ["/bin/sh", "-c", "指令碼路徑/stop.sh"]HTTP介面方式:
對於啟用SpringBoot actuator shutdown 能力時可配置Path為
/actuator/shutdown。非Spring應用可在再開啟SchedulerX SDK優雅下線HTTP介面後,配置Path為
/schedulerx/worker/shutdown。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app-image:latest
lifecycle:
preStop:
httpGet:
path: /schedulerx/worker/shutdown
port: 51886
scheme: HTTP方案三:阿里雲上應用發布平台自動整合
如果業務應用已經採用了公用雲端上EDAS或者MSE和ACK發布部署時,在對應的平台上開啟了無損下線能力即可自動整合SchedulerX定時任務的優雅下線能力。具體操作,請參見EDAS應用發布開啟應用無損下線和MSE+ACK部署形態下應用無損下線。