spring?batch線上異常定位記錄
前言
最近線上spring batch的一個(gè)問題圍繞博主近兩周時(shí)間,甚是擾神。具體現(xiàn)象為,spring batch執(zhí)行中莫名其妙線程就卡住了,不往下走了。下面會詳細(xì)描述整個(gè)問題的排查過程
環(huán)境說明
spring batch分區(qū)環(huán)境,共6個(gè)分片,兩臺實(shí)例,分別6個(gè)線程處理,由xxljob任務(wù)調(diào)度觸發(fā)日切job,配置由apollo管理。
排查過程
1.xxljob長連接導(dǎo)致
why?因?yàn)槲覀冇许?xiàng)目是老項(xiàng)目,任務(wù)調(diào)度使用的quartz,原來的批處理沒啥毛病。
然后修改了dayEndjob的觸發(fā)執(zhí)行改為異步,發(fā)現(xiàn)問題依舊。
2.定位JpaPagingItemReader的問題
盯著BATCH_STEP_EXECUTION看了很久,發(fā)現(xiàn)其他的step_execution都是啟動中的狀態(tài),其中兩個(gè)step_execution是讀取中,并且和其他step_execution明顯區(qū)別version版本一直在增加,初步判斷有線程一直在修改.但是日志一點(diǎn)動靜都沒有,如果是線程阻塞了,肯定也不存在線程修改數(shù)據(jù)庫數(shù)據(jù)。然后在apollo把日志級別調(diào)整成DEBUG級別(spring boot線上日志級別動態(tài)調(diào)整),發(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的問題
因?yàn)轫?xiàng)目使用了jpa。故而數(shù)據(jù)讀取器用用了JpaPagingItemReader,從異常信息找到JpaPagingItemReader文件后發(fā)現(xiàn),JpaPagingItemReader根據(jù)配置的transacted=true,編程式的開啟了事務(wù),而提交事務(wù)和回滾事務(wù)并沒有作try,catch處理,而一旦拋出了如上事務(wù)異常,因?yàn)镕aultTolerantChunkProvider 讀取數(shù)據(jù)實(shí)現(xiàn)如下

就會進(jìn)入一個(gè)一直拋異常的死循環(huán),至此所有問題都清晰明了了。
解決問題
參照J(rèn)paPagingItemReader既有的實(shí)現(xiàn),自定義一個(gè)CustomJpaPagingItemReader閱讀器,去掉事務(wù)部分代碼,或者實(shí)例化JpaPagingItemReader的時(shí)候設(shè)置transacted為false。這個(gè)參數(shù)主要用途我猜測是為了讓用戶自己選擇查詢出來的對象是否為entityManager管理的游離態(tài)。我們項(xiàng)目用不著,就直接去掉事務(wù)部分了。一般如果查詢沒問題,不會有如上情況,這個(gè)bug也是隱藏的深,死循環(huán)后info日志級別下沒有任何輸出,就和線程阻塞似的。解決這個(gè)問題后感覺神清氣爽啊
以上就是spring batch線上異常定位記錄的詳細(xì)內(nèi)容,更多關(guān)于spring batch線上異常定位的資料請關(guān)注腳本之家其它相關(guān)文章!
- 如何使用Spring Batch進(jìn)行批處理任務(wù)管理
- 使用Spring?Batch實(shí)現(xiàn)大數(shù)據(jù)處理的操作方法
- 使用Spring Batch實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程
- SpringBoot整合Spring Batch示例代碼
- SpringBatch結(jié)合SpringBoot簡單使用實(shí)現(xiàn)工資發(fā)放批處理操作方式
- Spring?Batch實(shí)現(xiàn)批量處理
- Spring?Batch批處理框架操作指南
- SpringBatch數(shù)據(jù)寫入實(shí)現(xiàn)
相關(guān)文章
詳解Spring Boot 自定義PropertySourceLoader
這篇文章主要介紹了詳解Spring Boot 自定義PropertySourceLoader,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases
這篇文章主要介紹了Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
myBatis組件教程之緩存的實(shí)現(xiàn)與使用
這篇文章主要給大家介紹了關(guān)于myBatis組件教程之緩存的實(shí)現(xiàn)與使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
IDEA不識別Java文件:文件變橙色&顯示后綴名.java的解決
這篇文章主要介紹了IDEA不識別Java文件:文件變橙色&顯示后綴名.java的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
spring boot + mybatis如何實(shí)現(xiàn)數(shù)據(jù)庫的讀寫分離
這篇文章主要給大家介紹了關(guān)于spring boot + mybatis如何實(shí)現(xiàn)數(shù)據(jù)庫的讀寫分離的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Spring Boot + Mybatis多數(shù)據(jù)源和動態(tài)數(shù)據(jù)源配置方法
最近做項(xiàng)目遇到這樣的應(yīng)用場景,項(xiàng)目需要同時(shí)連接兩個(gè)不同的數(shù)據(jù)庫A, B,并且它們都為主從架構(gòu),一臺寫庫,多臺讀庫。下面小編給大家?guī)砹薙pring Boot + Mybatis多數(shù)據(jù)源和動態(tài)數(shù)據(jù)源配置方法,需要的朋友參考下吧2018-01-01

