日誌寫爆後引發的乙個潛在Bug

2021-08-29 10:15:49 字數 1299 閱讀 1807

這周遇到乙個有點意思的bug,記錄一下,以示效仿。由於是公司內網環境下的,所以只能用拙劣的文本來做個記錄。

在開發的乙個程式,因為在測試中,開啟了debug日誌,然後50m乙個的日誌檔案大概10s就刷爆了。(插入乙個題外話,關於大日誌的問題,最近看了一篇文章:linux下日誌檔案過大解決方案,有興趣可以看一下)我司的日誌系統大概是這樣的寫滿足50m,就重新命名為***_1.log,再寫滿50m,就有***_1.log及***_2.log,從而保證***.log是當前正在寫入的日誌檔案。

對端是客戶端,我負責的的服務端。抓包看,一堆:tcp zerowindow,這是因為狂刷日誌的原因(這個是我猜的),導致機器處理不過來。客戶端的邏輯應該是遇到緩洪區滿(長時間發不了資料)後就重新連線。bug在於新的連線進來後,服務端沒有效應了。

最後週三晚上加班的時候,梳理了整個流程,分析關鍵日誌,檢視**等找到了這個bug的原因。因為每次的連線處理,服務端這邊都有一組狀態機(針對不同ip的連入)進行處理,比如0表示準備好了,可以連入,1表示已經連線成功,準備傳送資料,2表示傳送成功,準備收資料。每次處理完乙個連線後會把狀態值置為0,這樣下乙個連線就不受影響。但是因為緩衝區滿的原因,在服務端這邊還是處於資料處理過程(因為機器負荷滿了,所以從緩衝區讀資料慢),此時又有乙個新的相同ip的連線進來,因為發現上一次的連線還在處理中,所以本次的連線沒有進行處理。

//以下是偽** 表示對於連線進行乙個簡單的判斷

status[max_num_of_client] //每個客戶端的ip對應乙個狀態表示

//開始的做法是

if(status[i] == init_connect)

//修改後的做法

if(status[i] == init_connect)

else

因為同一ip連進來的是相的socketfd,所以上一次未處理完的資料也沒有繼續處理。解決方法也很簡單,在新的連線連入的時候,如果狀態機的值是0,就允許連入,如果非0就拒絕連入(closesocket),當客戶端發現服務端拒絕連入的時候,就會一直重連,這個過程中,服務端有時間處理上一次未處理完的資料,再處理新的連入。

此問題暴露我寫**時還是沒有考慮到異常情況,就是當已經在進行資料傳輸時,同乙個ip的再次連入會導致異常(理論上,應該是上一次斷鏈後,再發起新的連線),之前的測試,因為沒有遇到緩衝區滿了,客戶端未斷鏈就重連的情況所以也就沒發現此問題。後來和客戶端交流的時候,他們的開發信誓旦旦的表示他們一定是斷開連線後再發起新的連線,但抓包好像沒看到fin包這是有點詭異了!

後面的工作就是梳理這些複雜的日誌,分級,以及應該保留哪些日誌等,又是一體力活= =

乙個bug引發的感想

上周五,系統出現乙個bug。基本描述如下 b功能上傳乙個到 b路徑 a功能要獲取b路徑的,但是獲取路徑寫錯了,寫成了a路徑。線上突然出現此問題,訂單無法完成。該功能用到的頻率還比較大。無法馬上布版本。首先的想法想通過改資料來解決,但是發現不行。資料是動態的,不能改,也改不過來。其次的想法 新增b路徑...

乙個 passive 引發的bug

不是什麼很難的東西,權且做個記錄。首先說下背景,目前的專案中,需要同時繫結 wheel 和 scroll 事件。繫結 wheel,目的是開發 ctrl wheel 縮放頁面功能,此功能與瀏覽器本身的衝突,因此需要禁用滾輪原生功能,示意 window.addeventlistener wheel fu...

乙個int型別引發的bug

今天我在專案開發中,遭遇了乙個莫名其妙的問題,概括加抽象後形成如下問題 在使用mybatis的xml語句實現dao層介面 listselectbysome param record personexample example 時候,我寫的xml中有這麼一句 if test record.id nul...