新聞中心
著名IT作家、譯者侯捷老師以前在其著作中有句話,就是我們今天文章的標題「源碼面前,了無秘密」。可以說相當精煉。高度概括了從源碼中我們可以收獲的內(nèi)容。在源碼中,無論是應用的調用邏輯,關系,各種設計都一目了然。

成都創(chuàng)新互聯(lián)于2013年成立,先為三門等服務建站,三門等地企業(yè),進行企業(yè)商務咨詢服務。為三門企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
為什么會突然想到這樣一個題目呢?
是因為最近一個項目上線,其中有幾個功能模塊使用了 Redis 進行數(shù)據(jù)的緩存,包括權限信息也在其中。所以每個請求都會通過 Redis 進行鑒權。這塊功能是我指導的一個小同學負責開發(fā)的。上線幾天后出現(xiàn)了這樣的問題:
問題現(xiàn)象是線上出現(xiàn)了大量的錯誤
- Cannot get Jedis connection; nested exception
- is redis.clients.jedis.exceptions.JedisException:
- Could not get a resource from the pool
項目約等于小流量,上線時 Redis 的***連接數(shù)開到了1000,用戶數(shù)遠小于***連接數(shù),Redis 使用的是公司的集群,穩(wěn)定性也有保障,理論上是不該出現(xiàn)這種取不到資源的情況的。
小同學自行 Google了好久沒找到問題具體原因。我提供的幾個思路也沒本質解決問題。不過好在調整配置可以在線下穩(wěn)定復現(xiàn)。所以我在小同學的電腦上開始debug,跟源碼。
和結對編程類似,我一邊Debug,我一邊給小同學講 Redis 這個連接池的實現(xiàn)思路,目前懷疑的問題等等。小同學說自己剛才也在試著跟源碼,但跟了兩層之后,感覺調用越來越深,有點暈,就放棄了。
然后我繼續(xù)Debug和講原理,跟到資源使用完畢,在 finally 進行釋放回收的地方,發(fā)現(xiàn)有處代碼在判斷當前的 dataSource是否為空,從而執(zhí)行兩種不同的操作。 如果不為空,則會將資源放回pool中,便于下次繼續(xù)使用,為空則真正的進行close的操作,直接將Socket關閉了。而這兩個if/else的邏輯是封裝在一個方法中,不跟進來不會發(fā)現(xiàn)區(qū)別對待。
而且我們當前在用連接池,預期是按連接池的思路,使用完畢的需要釋放回池中繼續(xù)下次的使用,當前這個現(xiàn)象就比較怪異了。
繼續(xù)向前,發(fā)現(xiàn)整體雖然Connection 使用的是JedisConnection,但在我們出問題的這里,返回的是個其子類JedisWrapper,這個是部門同學開發(fā)的一個SpringBoot 的 starter,重寫了一部分邏輯,將連接對象作為原始對象持有,我們并沒有用到其中的特性。上面判斷dataSource是否為空本來是要判斷JedisConnection里該屬性是否為空,在Wrapper之后,是保存了origin的對象,返回的是個new Wrapper,這樣dataSource并沒有初始化,就出現(xiàn)了前面dataSource為空的問題。
跟到這里,發(fā)現(xiàn)是maven 的依賴不同,切換回標準的 SpringBoot starter,問題解決了。
小同學感嘆道,「這不是造孽么,如果不是你幫我,不知道從哪下手分析了?!?/p>
我則鼓勵小同學沒有思路的時候,可以從源碼里找找,跟代碼的過程,也是學習的過程,比如這次就可以在跟的時候了解連接池具體是怎樣實現(xiàn)的。任何問題在源碼中都無處遁形,況且這些源碼也可能有Bug呢。
回過頭來,我們不難發(fā)現(xiàn),可能不是所有的問題都需要跟源碼,但閱讀源碼,帶著問題 Debug,本身就像你放大招一樣,雖然費時費力,但收獲也會很多,一招制敵。這也是開源帶來的好處,可能通過源碼來分析作者的思路,在問題產(chǎn)生時可以逐行分析,了解細枝末節(jié),這些都是C/C++里dll文件所不具備的優(yōu)勢。:-)
對于新同學,可能對于源碼閱讀有畏難情緒,感覺這一層層的嵌套,調用有點找不著頭緒。但這些都是表象,你試著跟幾次就輕車熟路了。
老司機為什么稱為老司機,一是車技好,二是熟悉車況。這些也都是練出來的。
所以無論是做為解決問題的***手段,還是學習設計與思想的寶庫,源碼都是不二之選,有時間的時候,可以多看看,不久之后,你也會是老司機。
***,總結下一般出現(xiàn)問題時,跟源碼的思路
- 如果有異常,可以利用IDE的異常斷點,這樣異常產(chǎn)生時,一個鮮活的異常棧就獲取到了,完整的調用鏈就在你眼前。
- 逐級深入,先分塊找到懷疑的目標方法,結合前一步,跟進
- 具體方法時,不要根據(jù)表現(xiàn)的方法名,參數(shù)來猜方法的意圖,必要時進去看一眼,萬一有隱藏邏輯呢
- 同樣的類,看看包名、類名,是否是加載的類不對導致
【本文為專欄作者“侯樹成”的原創(chuàng)稿件,轉載請通過作者微信公眾號『Tomcat那些事兒』獲取授權】
分享題目:源碼面前,了無秘密
分享網(wǎng)址:http://m.fisionsoft.com.cn/article/djdgisd.html


咨詢
建站咨詢
