spring?batch線上異常定位記錄
前言
最近線上spring batch的一個問題圍繞博主近兩周時間,甚是擾神。具體現(xiàn)象為,spring batch執(zhí)行中莫名其妙線程就卡住了,不往下走了。下面會詳細描述整個問題的排查過程
環(huán)境說明
spring batch分區(qū)環(huán)境,共6個分片,兩臺實例,分別6個線程處理,由xxljob任務調度觸發(fā)日切job,配置由apollo管理。
排查過程
1.xxljob長連接導致
why?因為我們有項目是老項目,任務調度使用的quartz,原來的批處理沒啥毛病。
然后修改了dayEndjob的觸發(fā)執(zhí)行改為異步,發(fā)現(xiàn)問題依舊。
2.定位JpaPagingItemReader的問題
盯著BATCH_STEP_EXECUTION看了很久,發(fā)現(xiàn)其他的step_execution都是啟動中的狀態(tài),其中兩個step_execution是讀取中,并且和其他step_execution明顯區(qū)別version版本一直在增加,初步判斷有線程一直在修改.但是日志一點動靜都沒有,如果是線程阻塞了,肯定也不存在線程修改數(shù)據(jù)庫數(shù)據(jù)。然后在apollo把日志級別調整成DEBUG級別(spring boot線上日志級別動態(tài)調整),發(fā)現(xiàn)輸出大量的如下日志信息
java.lang.IllegalStateException: Transaction already active at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:42) at org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:197) at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108) at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:88) at org.springframework.batch.item.support.SynchronizedItemStreamReader.read(SynchronizedItemStreamReader.java:55) at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy126.read(Unknown Source) at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91) at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87) at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:116) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:110) at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69) at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:272) at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
3.確定JpaPagingItemReader的問題
因為項目使用了jpa。故而數(shù)據(jù)讀取器用用了JpaPagingItemReader,從異常信息找到JpaPagingItemReader文件后發(fā)現(xiàn),JpaPagingItemReader根據(jù)配置的transacted=true,編程式的開啟了事務,而提交事務和回滾事務并沒有作try,catch處理,而一旦拋出了如上事務異常,因為FaultTolerantChunkProvider 讀取數(shù)據(jù)實現(xiàn)如下
就會進入一個一直拋異常的死循環(huán),至此所有問題都清晰明了了。
解決問題
參照JpaPagingItemReader既有的實現(xiàn),自定義一個CustomJpaPagingItemReader閱讀器,去掉事務部分代碼,或者實例化JpaPagingItemReader的時候設置transacted為false。這個參數(shù)主要用途我猜測是為了讓用戶自己選擇查詢出來的對象是否為entityManager管理的游離態(tài)。我們項目用不著,就直接去掉事務部分了。一般如果查詢沒問題,不會有如上情況,這個bug也是隱藏的深,死循環(huán)后info日志級別下沒有任何輸出,就和線程阻塞似的。解決這個問題后感覺神清氣爽啊
以上就是spring batch線上異常定位記錄的詳細內(nèi)容,更多關于spring batch線上異常定位的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot讀取properties或者application.yml配置文件中的數(shù)據(jù)
這篇文章主要介紹了SpringBoot讀取properties或者application.yml配置文件中的數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06Java線程池ThreadPoolExecutor源碼深入分析
ThreadPoolExecutor作為java.util.concurrent包對外提供基礎實現(xiàn),以內(nèi)部線程池的形式對外提供管理任務執(zhí)行,線程調度,線程池管理等等服務2022-08-08實現(xiàn)quartz定時器及quartz定時器原理介紹
Quartz是一個大名鼎鼎的Java版開源定時調度器,功能強悍,使用方便,下面我們看看如何使用它2013-12-12解決org.apache.ibatis.binding.BindingException:?Invalid?boun
這篇文章主要介紹了解決org.apache.ibatis.binding.BindingException:?Invalid?bound?statement?(not?found)問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05