多線程網路程序有什麼好的調試方法?
當大並發上來時 可能會碰上多線程資源訪問衝突類型的問題,比如該加鎖的未加鎖。這類問題往往你一單步跟蹤,它就不出問題了。甚至並發的壓力一小,也不出問題了。可是壓力一大,又往往日誌一片混亂。
處理這類問題,要學會幾個常規的調試小竅門。
一是記得為你的上層業務的網路報文,加一個全局唯一的id,比如一個uuid。回頭出錯時,可簡單寫個工具,從日誌中挖出這個任務的獨立的完整過程。
二是,當然一些錯誤有時必須交叉看所有日誌,反倒才有幫助是不是? 所以日誌一定要有線程id,要有相關的socket連接編號,客戶端的ip加埠加一個time_t通常可用作這個編號。還要有至少精確到毫秒的時間。如果問題邏輯居然跨多台主機(這不很常見嗎?),現場搞台時間伺服器 ,確保各台網路伺服器至少在秒級上保持一致。難道許多看似穿越的bug,不是因為有太依賴時間的邏輯,可是有某主機停留在1970年的時光里造成的?
還有,再強調下,一個好的log機制一定是調試多線程網路程序的基礎工具。它至要保證,打到屏幕上或文件的日誌,不會因為並發而混亂(就是保證一條日誌輸出的完整性,別夾雜另一條日誌的部分),並且最好支持在屏幕上彩色顯示,一定要有級別(信息,警告,錯誤,失敗,調試,臨時)控制,並且最好是可在運行期調換級別,一定要能方便地輸出前面說的各類id及時間,最好也支持必要時依據當前調用的函數棧級自動處理縮進,還最好要有信息詳細級別控制,也會有不想看線程id或時間的時候。
最後,一定要學會正確使用assert。該死就讓它死,有利於找到問題,所有該自殺不自殺,非要帶病運行的,都是作。因為c++多線程程序很調皮,它最喜歡讓帶病程序時好時抽。
最最後,當程序段錯誤了,一定要學會讓留它下core文件,太多太多看似頭大的問題,用gdb(或其它調試器)來個現場恢復,立刻水落石出。並且幾乎都是並發問題。
最最最後,別忘了有tcptrace這樣的工具,你的調試器再強,它也是只調一個節點上的一個網路相關進程,兩個程序網路通信,到底是誰說錯話呢?。用tcptrace中間一插手,清清楚楚,當然你不要程序邏輯還沒正確,就開始上ssl追求安全。這也是一個必須的做法:你的要支持ssl的網路交互的實現,一定要實現成有可方便地切換回不帶ssl的機制。
幾個最後了?反正學個python,花點時間把你負責的網路模塊的上下家,都寫出來,當然不需要內部邏輯,只需要能互相喂數據,這樣媽媽再也不用擔心你自己測試不了自己的網路節點程序了,特別是當你的上家是一個豬一樣的隊友時,自行搞定上家的輸出,簡直是不加班的利器。py不會也沒關係,用c++也可。如果上家是個純粹的客戶端,網上找找就有通用的。
首先線程模型要清晰,thread per connection、reactor+thread pool、one loop per thread等等。
然後就跟普通多線程程序一樣調試,無非是log+trace+debugger。開發多線程的程序應該注意哪些問題?
一個靠譜的日誌系統,合理的日誌輸出內容。
用線程鎖的時候,小心小心再小心。
最後把伺服器的core dump設置好(假設你的平台是linux)。
如果還是搞不定多線程網路程序,那麼要麼換個靠譜的碼農來干這個活,要麼就老老實實用單線程吧。
發布前單步+日誌+斷言等等任何調試手段.
發布後日誌...和現場.(維護人員往往保留現場不完整導致開發分析不出原因來)
推薦閱讀:
※如何思考並解決網路編程中的問題?
※windows 利用socket實現從http下載?
※想問下php的socket的工作流程是什麼?
※Socket是一個好的設計嗎?
※有沒有哪些高效的c++ socket框架?