本文介紹如何處理使用SchedulerX過程中的一些任務管理問題。
Spring應用找不到Bean怎麼辦?
通過應用管理串連機器查看啟動方式,確保為Spring或者Spring Boot方式。
JobProcessor要注入為bean,比如加@Component註解。排查Pom依賴如果依賴
spring-boot-devtools則需要排除掉。如果JobProcessor和process方法有aop註解,需要升級到最新版本SchedulerX用戶端,低版本不支援aop。
因為多加了一層代理導致Bean類型不符。可以把斷點放入
DefaultListableBeanFactory類中。其中beanDefinitionNames成員變數是Spring註冊的Bean列表, 裡面可以看到Bean被某切面代理,例如一些使用者間接引入一個錯誤的二方庫導致該現象,排除掉即可。

如果以上方案無法解決問題,可以調試ThreadContainer.start方法。如果class.forName報錯,class又確實存在,可能是業務方使用了某些架構,導致classLoader不一致,可以通過設定SchedulerxWorker.setClassLoader解決。
任務失敗,報錯“Unable to make fileld private”
MapReduce用到了序列化和還原序列化架構,從 Java 9 版本開始,反射私人變數需要手動開啟。請在JVM參數中添加以下配置:
--add-opens java.base/java.lang=ALL-UNNAMED任務失敗,報錯“submit jobInstanceId to worker timeout”
當應用發布的時候報該問題或者偶爾報該問題時,無需處理。
如果持續報錯且每次報錯的workerAddr都是同一台機器,說明服務端和用戶端長串連斷開,需要將該Worker節點重啟或者升級SchedulerX用戶端版本至最新版本。升級至最新版本後,斷開的長串連可自動回復。
任務失敗,報錯“used space beyond 90.0%!”
磁碟已滿,需要清理ECS或者容器上的磁碟空間。
任務失敗,報錯“ClassNotFoundException”
說明執行任務的Worker上沒有該類,請確保Java任務配置的Processor類名必須是類的全路徑,並非簡寫。
如果配置的jobProcessor類名正確,即為Worker上沒有該類,一般為使用者發錯包或者該應用還串連了其他人的機器。您可以自己登入Worker機器,通過反編譯查看詳細情況。
任務失敗,報錯“jobInstance=xxx don't update progress more than 60s”
正在運行任務的Worker停止工作或者發布時,超過60秒沒有彙報進度時,會被服務端強制終止。如果確定問題由Worker引入或者該Worker已經不存在,則無需處理。
任務執行失敗,且沒有錯誤資訊
問題現象:
任務執行失敗,且沒有錯誤資訊。
可能原因:
機器或商務邏輯執行失敗等。
解決方案:
在執行列表頁面,選擇任務執行個體列表,在任務執行個體列表欄,選擇對應的任務,單擊操作列下的詳情,進入任務執行個體詳情,查看對應執行失敗的機器。
如果沒有子任務詳情,說明為簡單任務。查看基本資料的workAddr,該機器為執行任務的業務機器。
登入業務機器,開啟~/logs/schedulerx/worker.log日誌。
執行
grep <執行個體ID> worker.log查看該執行個體相關的日誌。如果有ERROR層級異常,查看堆棧的具體原因。錯誤描述為空白則基本為商務邏輯執行失敗且未返回失敗資訊,請先自行排查商務邏輯。
錯誤描述有架構異常,請加入釘群(釘群號:23103656)聯絡SchedulerX技術支援人員。
如何排查任務失敗的原因?
如果是單機任務,業務直接拋異常,可以在執行列表頁面,單擊任務執行個體列表,在對應任務執行個體的操作列,單擊詳情查看錯誤資訊。
如果任務沒有拋異常或者使用了分布式任務,您的專業版應用可以通過Log Service來排查問題。
如果是基礎版應用,您可以自行登入Worker節點,查看SchedulerX的日誌和業務自己的日誌進行排查。
任務運行中卡住怎麼辦?
問題現象:
調度任務一直處於執行中,不能結束。
可能原因:
業務的問題。
SchedulerX的問題。
解決方案:
業務方面的問題可以按照以下方案排查,其他問題請加入釘群(釘群號:23103656)聯絡SchedulerX技術支援人員。
專業版應用:可以通過控制台的查看堆棧功能(1.4.2及以上用戶端版本可用),來排查任務異常的堆棧。
基礎版應用:可以自行登入卡住的Worker節點,通過
jstack命令查看堆棧,執行命令。jstack <pid> | grep <任務執行個體id> -A 20
如何排查任務運行慢的原因?
開啟專業版,使用鏈路追蹤。具體操作,請參見如何接入鏈路追蹤。
任務運行執行個體達到上限怎麼辦?
問題現象:
在任務管理頁面,單擊運行一次,收到任務運行執行個體達到上限,請稍後重試提示。
可能原因:
該任務已經有任務執行個體在運行中。
運行中的任務執行個體達到任務配置的最大並發數。
解決方案:
如果並發數合理,無需處理。可以在任務管理頁面,單擊查看運行中的任務執行個體
如果不合理,在目標任務的操作列,單擊編輯,在進階配置裡設定執行個體並發數。
任務上一次沒運行完,下一次是排隊還是不運行了?
任務預設並發是1,即串列跑。如果任務執行時間比較長,上一次沒運行完,下一次調度時間到了,則下一次會直接丟棄,不會運行也不會排隊。
如果設定任務執行個體並發數為2,上一次沒運行完,下一次時間到了仍然可以運行一個執行個體,最多同時運行兩個任務執行個體。
如何設定一次性任務?
SchedulerX 2.0支援設定一次性任務。時間類型選擇one_time即可。一次性任務不保留任務執行記錄。
one_time任務運行完成後怎麼查看記錄?
one_time任務運行完會自動銷毀,防止資料堆積,且不保留任何記錄。如果需要儲存記錄,您可以開啟Log Service,保留最近兩周所有任務的執行日誌,方便排查問題。關於如何開啟Log Service,請參見應用管理。
如何進行秒層級調度?
SchedulerX支援秒層級調度。cron、fix_rate不支援秒層級調度,您可以選擇時間類型為second_delay,即上一次運行完之後間隔幾秒再運行。
某個時間點沒有調度怎麼辦?
某個單機任務有一個時間點沒有調度運行時,您需要確認機器列表是否存在機器,並確認機器是否全部處於繁忙狀態。如果不存在機器,按無可用機器或機器繁忙進行排查。更多資訊,請參見無可用機器(no worker available)和機器繁忙(all workers are busy)該怎麼辦?。
建議為任務配置無可用機器警示。具體操作,請參見任務管理。
SchedulerX如何設定逾時時間?
SchedulerX不支援子任務層級的逾時時間,只支援整個任務的逾時。可以通過控制台動態修改逾時時間。具體操作,請參見任務管理。
為什麼執行個體停止之後還會執行?
問題現象:
執行個體停止之後仍然執行。
可能原因:
任務執行個體停止後,SchedulerX會把Kill訊息發送到用戶端。用戶端接收到Kill訊息後,會停止下發和停止執行未執行的子任務、銷毀該執行個體的上下文、銷毀執行個體所有的線程池。對於已經在執行中的子任務不會被停止掉,只會中斷對應的線程,所以子任務會繼續運行直到結束。
解決方案:
一般情況下,您無需處理,等待子任務執行結束即可。
如果確實需要停止後立即結束所有運行中的任務,需要修改子任務處理邏輯,增加對當前線程Interrupt狀態的處理。
如何進行任務管理進階配置?
更多資訊,請參見任務管理進階配置參數說明。
機器繁忙(all workers are busy)該怎麼辦?
可以在應用管理頁面查看執行個體,定位繁忙狀態的Worker,然後單擊繁忙,即可查看超過了閾值的指標。


繁忙的閾值在應用管理頁面通過編輯應用分組配置。

如果是load繁忙,您需要查看自己是否為容器(K8s)部署。如果為容器(K8s)部署,需要配置以下兩個參數,否則採集的CPU使用率可能不準確。具體操作,請參見Spring Boot應用接入SchedulerX。
key | 描述 | 設定值 | 起始版本 |
spring.schedulerx2.enableCgroupMetrics | 是否使用cgroup統計用戶端執行個體的指標。容器(K8s)環境需要自己手動開啟。 | true/false,預設false。 | 1.2.2.2 |
spring.schedulerx2.cgroupPathPrefix | 容器內cgroup的路徑。 | 預設是/sys/fs/cgroup/cpu/,如果存在該路徑則不需要設定。 | 1.2.2.2 |
如何接入鏈路追蹤?
任務調度支援全鏈路追蹤。具體操作,請參見如何接入鏈路追蹤。
應用發布過程,任務執行卡住或變慢
問題現象:
應用發布過程,任務執行卡住或變慢。
可能原因:
對於分布式任務,處理子任務的機器下線會進行重新分發並輪詢檢查機器是否線上,會導致整個處理過程變慢。
解決方案:
將用戶端升級至最新版本,1.7.9及以上版本該現象會得到最佳化。
單擊運行一次後,系統提示輸入執行個體參數,如何處理?
在任務管理頁面的操作列,單擊運行一次,可以執行一次該調度任務。彈框中的執行個體參數非必填,主要用於測試。

單擊運行一次並輸入執行個體參數,那麼代碼中擷取的是執行個體參數還是任務參數?
執行個體參數與任務參數是兩個不同的概念,代碼中具體擷取的參數是由使用者的業務代碼決定的。
如何擷取任務參數或者執行個體參數?
詳細代碼如下所示。
@Component
public class JavaDemoProcessor extends JavaProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger("schedulerxLog");
@Override
public ProcessResult process(JobContext jobContext) throws InterruptedException {
LOGGER.info(JSON.toJSONString(jobContext));
//擷取任務參數
String jobParameters = jobContext.getJobParameters();
//擷取執行個體參數
String instanceParameters = jobContext.getInstanceParameters();
LOGGER.info("任務參數:" + jobParameters);
LOGGER.info("執行個體參數" + instanceParameters);
return new ProcessResult(InstanceStatus.SUCCESS);
}
}如何?填寫執行個體參數後,代碼預設擷取執行個體參數,未填寫則擷取任務參數
詳細代碼如下所示。
@Component
public class JavaDemoProcessor extends JavaProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger("schedulerxLog");
@Override
public ProcessResult process(JobContext jobContext) throws InterruptedException {
String params = null;
if (StringUtils.isNotBlank(jobContext.getInstanceParameters())) {
params = jobContext.getInstanceParameters();
} else {
params = jobContext.getJobParameters();
}
LOGGER.info("JavaDemoProcessor params:{}", params);
return new ProcessResult(InstanceStatus.SUCCESS);
}
}