我現(xiàn)在就職于一家中型的互聯(lián)網(wǎng)企業(yè)卖子,去年年底入職的薪資和待遇都很不錯,但是總結(jié)起來說的好聽就是全村人的希望洋闽,說的不好聽就是一個人幾乎干了一個項(xiàng)目組的事诫舅。下面是我的一次項(xiàng)目救火經(jīng)歷(背鍋經(jīng)歷)。就是年后的一個合作公司上線了一個子業(yè)務(wù)系統(tǒng),對接公司內(nèi)部的單點(diǎn)系統(tǒng)匾浪。我收到該公司的技術(shù)咨詢:項(xiàng)目啟動后沒有規(guī)律的突然無法登錄了,重新啟動后卷哩,登錄一斷時(shí)間后又無法重新登錄,對方技術(shù)人員一頭霧水不知道什么原因冷溶,后臺日志沒有任何錯誤信息尊浓。我臨危受命,趕往該項(xiàng)目進(jìn)行撲火工作虏劲,其實(shí)本來2天都可以解決的問題褒颈,讓我花了5天解決谷丸。具體原因待我一一解釋。
1泉唁,未掌握log日志的精髓
log日志的debug,info亭畜,error信息亂打,該用debug的用info,該用info的用debug......拴鸵,導(dǎo)致的結(jié)果就是一個登陸成功請求劲藐,后臺日志打了300行代碼,嚴(yán)重影響了排查追蹤問題的效率兄渺,項(xiàng)目線上日志級別仍為debug級別汰现,換成info級別呢,結(jié)果好多關(guān)鍵信息又沒有打印凳兵。
日志輸出格式的關(guān)鍵信息不完善,該日志是在哪類目名饭望、發(fā)生的線程,以及在代碼中的行數(shù)都沒有清楚的顯示出來哨啃,這個日志是哪里打印的都無從知曉苇倡。
關(guān)于這里囤踩,我想說的是,會的框架再多综慎,spark示惊,flink,hadoop米罚,消息中間件等各種上層框架配置的在溜只是花拳繡腿录择,log日志是內(nèi)功,它是日后面對各種線上問題能夠快速排查的一種手段辨宠。
下面這個是他的日志輸出:
2嗤形,核心參數(shù)不做判斷
方法返回的數(shù)據(jù)不做null或""字符串判斷弧圆,導(dǎo)致各種情況的空指針異常。項(xiàng)目的功能都是理想化霹期,預(yù)想我就是需要這些數(shù)據(jù)才能給你正確的結(jié)果拯田,否則哪里出錯我不知道船庇。這個問題導(dǎo)致我在還原案件現(xiàn)場時(shí)給我造成極大的困惑,一不留神一個空指針錯誤臣淤,我必須對這個錯誤進(jìn)行加強(qiáng)的判斷處理窃爷,好方便我模擬出登錄多次后無法登錄的情況按厘。
另外項(xiàng)目中sql語句的in的使用不規(guī)范,結(jié)合前面的null判斷沒有遮咖,出現(xiàn)一種:"咦造虏,我用這個賬號登錄就成功了麦箍,sql是正確的陶珠,用這個人的賬號登錄揍诽,怎么就報(bào)sql語法不正確啊,明明調(diào)用的是同一塊的代碼啊"
很明顯的roleid為"'字符串的話渠啤,這條sql語句的語法是由問題的沥曹。
我特意整理了一下碟联,里面的技術(shù)不是靠幾句話就能講清楚,所以干脆找朋友錄制了一些視頻壶栋,很多問題其實(shí)答案很簡單贵试,但是背后的思考和邏輯不簡單凯正,要做到知其然還要知其所以然毙玻。如果想學(xué)習(xí)Java工程化、高性能及分布式漆际、深入淺出。性能調(diào)優(yōu)夺饲、Spring奸汇,MyBatis往声,Netty源碼分析的朋友可以加我的Java進(jìn)階群:582100479擂找,群里有阿里大牛直播講解技術(shù),以及Java大型互聯(lián)網(wǎng)技術(shù)的視頻免費(fèi)分享給大家浩销。
3贯涎,局部變量提升為靜態(tài)變量
這個是文章開頭提的問題的原因,因?yàn)榈卿浺騿吸c(diǎn)系統(tǒng)驗(yàn)證用戶的身份慢洋,所以它采用httpclient框架來發(fā)送http請求塘雳,它在這里把httpclient的變量作為一個靜態(tài)變量陆盘,然后在方法里面復(fù)用該對象,然后方法里面調(diào)用完該對象又沒有釋放資源合理的close败明,這個框架默認(rèn)會維護(hù)一個連接池隘马,如果你申請一個資源使用后不釋放,那么該資源將不被下一個請求使用妻顶,新的請求必須在等待隊(duì)列中等待酸员,然后當(dāng)用戶登錄20次后,把資源池中的請求都耗盡了讳嘱,新的請求拿不到資源位于等待隊(duì)列中不斷等待幔嗦,導(dǎo)致服務(wù)器超時(shí),登錄失敗504錯誤邀泉。
當(dāng)時(shí)我看到這個類的靜態(tài)變量時(shí)httpclient的時(shí)候,我心中就飄起不好的預(yù)感叛氨,此處是一個容易出錯的地方呼渣,如果是我,對這個框架寞埠,這個類沒有十足的把握屁置,我會它把整成局部變量,這樣在低并發(fā)下仁连,就讓GC去幫我回收吧蓝角。
改造后:
4,攔截器的路徑規(guī)劃混亂
這個問題也為我排查問題造成了阻礙饭冬,排查登錄問題使鹅,我首先要把它一次登錄成功后后端走的方法軌跡追蹤出來,看到底是哪一個環(huán)節(jié)的代碼問題昌抠,因?yàn)闆]有任務(wù)錯誤信息患朱。他的攔截器呢,一個登錄請求成功攔截器反復(fù)執(zhí)行了三次炊苫,中間至少有一次攔截器是沒有做任何有效出來裁厅,出現(xiàn)這的問題是他前端業(yè)務(wù)發(fā)送無關(guān)的請求,被攔截導(dǎo)致的侨艾,這個逼得我通過日志插樁計(jì)數(shù)來還原勾勒出它的完整路徑,為我審查代碼找到調(diào)用httpclient這一塊的代碼問題提供的機(jī)會唠梨。
5袋励,亂用try catch
這個也很惡心,它的代碼突然try catch包裝一下,咦茬故,這個家伙得不錯盖灸,還對某些異常進(jìn)行特殊打標(biāo)記錄,我仔細(xì)看了一下代碼均牢,這是什么鬼啊糠雨,catch中怎么把異常信息吃了,吃了就吃了徘跪,你為啥也不打印異常信息甘邀,也不throws異常,就這樣兇猛的將異常吃了垮庐,明明有問題松邪,它不報(bào),通過它來引發(fā)一個新的異常來雪藏真正的問題哨查。
最后我想說逗抑,程序員何苦難為程序員,代碼留一線寒亥, 日后好相見啥邮府。你也不想自己給自己挖坑后,解決不了溉奕,然后來一句"大哥褂傀,你忙嗎,我這有個小問題加勤,幫忙看下唄(嗑瓜子)"仙辟。
如果對java微服務(wù)、分布式鳄梅、高并發(fā)叠国、高可用、大型互聯(lián)網(wǎng)架構(gòu)技術(shù)戴尸、面試經(jīng)驗(yàn)交流粟焊。感興趣可以關(guān)注我的頭條號,我會在微頭條不定期的發(fā)放免費(fèi)的資料鏈接孙蒙,這些資料都是從各個技術(shù)網(wǎng)站搜集项棠、整理出來的,如果你有好的學(xué)習(xí)資料可以私聊發(fā)我马篮,我會注明出處之后分享給大家沾乘。歡迎分享怜奖,歡迎評論浑测,歡迎轉(zhuǎn)發(fā).
我特意整理了一下,里面的技術(shù)不是靠幾句話就能講清楚,所以干脆找朋友錄制了一些視頻迁央,很多問題其實(shí)答案很簡單掷匠,但是背后的思考和邏輯不簡單,要做到知其然還要知其所以然岖圈。如果想學(xué)習(xí)Java工程化讹语、高性能及分布式、深入淺出蜂科。性能調(diào)優(yōu)顽决、Spring,MyBatis导匣,Netty源碼分析的朋友可以加我的Java進(jìn)階群:582100479才菠,群里有阿里大牛直播講解技術(shù),以及Java大型互聯(lián)網(wǎng)技術(shù)的視頻免費(fèi)分享給大家贡定。