【Takin 應用日記】記一次 TransmittableThreadLocal 引起的業務異常

數列科技發表於2021-08-13

對於常見的WEB容器,Takin透過增強org.apache.catalina.core.StandardHostValve#invoke方法,攔截並解析方法入參的Request物件中的header資料,判斷壓測標的資訊並將壓測標以及鏈路資訊設定到上下文物件,並透過ThreadLocal儲存該上下文物件,以此來保證當前執行緒處理的過程中都能獲取到壓測標以及鏈路資訊。


undefined

但是不管是WEB容器還是業務程式碼經常會使用執行緒池執行程式碼,這時候ThreadLocal就有侷限性了,如何做到跨執行緒池傳遞我們的上下文物件就顯得異常重要了,好在Alibaba的   解決了這個問題,具體transmittable-thread-local的詳細內容大家可以透過git地址檢視,這裡我們主要以git上的demo看看transmittable-thread-local如何實現跨執行緒傳遞的,主要透過將執行緒池執行的Runnable物件包裝成TtlRunnable物件並儲存當前的上下文資訊。這樣就完成了對執行緒池執行任務的壓測標以及鏈路資料資訊的透傳,至此似乎一切都很完美。

undefined
undefined
undefined

直到某次出現了一個詭異的現象,在使用Takin的過程中,有一應用接入Takin之後,某個功能無法正常使用,但是無論是應用的日誌還是Takin的日誌都未顯示任何異常資訊,再追問了無法使用的功能是一個執行緒池執行任務,當時擴充套件了ThreadPoolExecutor的beforeExecute方法和afterExecute方法,用以記錄任務執行的耗時,並且會列印任務的taskId等資訊,透過截圖的Debug資訊便可以看到問題出現了,由於使用了transmittable-thread-local導致原始的Runnable被包裝成了TtlRunnable物件,在這個過程中如果業務想要再獲取Runnable物件強轉獲取一些任務資訊,就會出現類無法轉換的異常。

解決方案的話目前可以透過增強beforeExecute和afterExecute方法,對Runnable物件進行判斷,如果是TtlRunnable物件,則透過TtlRunnable.getRunnable()方法返回原是的Runnable物件

undefined
undefined

Takin開源詳情
立即掃碼,入群技術交流~
undefined


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004063/viewspace-2786768/,如需轉載,請註明出處,否則將追究法律責任。

相關文章