如何將任務調度應用優雅下線
本文介紹如何將任務調度應用優雅下線。
背景信息
在實際業務場景下,定時任務持續地按固定頻率在應用進程中執行。當應用在發布重啟時,進程需暫時下線。如果直接關閉應用,正在進行中的定時任務將被中斷,可能導致數據不完整或其他問題。為避免該情況,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事件處理來觸發應用的優雅下線,同時preStep 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部署形態下應用無損下線。