怎麼提升寫代碼的能力 第一段:第一次感受每天億級系統的挑戰 第二段:民間“消防隊”的故事 第三段:重寫通信框架 第四段:學習 JVM 總結

簡介: 對於程序員而言,我始終認爲代碼是展現能力的關鍵,一個優秀程序員寫的代碼,和一個普通程序員寫的代碼是很容易看出差別的,代碼作爲程序員的硬實力和名片的展示,怎麼提升寫代碼的能力始終是一個關鍵的話題,不過很遺憾這篇文章其實也不是講具體的步驟、銀彈方法、武功祕籍什麼的,這篇文章講講我自己印象中對我寫代碼能力提升比較大的四段經歷,也許可供參考。


第一段:第一次感受每天億級系統的挑戰

2008 年,HSF 的第二個版本,在當時淘寶最重要的交易中心上線,上線當天造成淘寶網站訪問巨慢,交易類的頁面幾乎打不開,最後靠下線 HSF 才恢復。

下線後開始查問題,HSF 的第二個版本基於的是 jboss-remoting,jboss-remoting 在當時的版本里遠程同步調用的超時時間是寫死在代碼裏的 60s,而調用的服務確實會有一些超過 10 幾秒的現象出現,導致了 web 應用處理 web 請求的線程池被這些慢請求給逐漸佔據,請求堆積,最終呈現出了頁面打開非常慢的現象。

查清原因後,決定基於當時的 Mina 重寫整個 HSF 的通信,重寫的這兩個月時間對我自己寫代碼的能力有很大的提升,無論是對網絡 IO 方面處理的深入學習,還是在高併發系統上的深入學習,現在想想學習的方式也就是翻各類網絡 IO 的科普資料,然後是讀 Mina 的源碼、Java 網絡 IO 的源碼,併發這塊的學習主要還是靠那本經典的《Java 併發編程實戰》,以及讀 Java J.U.C 裏的代碼,這段時間的學習相比以往翻 Think in Java 之類的最大區別是,學習後付諸實踐,隨着 HSF 這個新的重寫的版本的上線,基本算是逐漸真正掌握了這些部分的代碼能力。

除了代碼能力的提升外,得到了另外一個最大的教訓就是,對於一個億級且長時間運行的系統,很多看起來的小概率的問題都一定會成爲嚴重的問題,這也是爲什麼寫高併發系統的難度,要求了必須對自己寫的代碼,以及自己代碼調用到的各種 API 裏的實現都非常的清楚,這樣才能真正確保最終代碼的魯棒性。

第二段:民間“消防隊”的故事

第二段對我自己寫代碼能力提升特別大的經歷是在民間"消防隊"的那段日子,淘寶在 2009 年故障特別多,但處理故障還沒有一個標準的體系和組織,導致很多時候會出現故障出了都沒什麼人處理,或者處理效率不高,於是當時有個運維團隊的同學拉了一些人組建了一個羣,羣的名字叫淘寶消防隊,用來處理淘寶出現的各種故障,我很湊巧的也加入了這個羣,這個羣裏還有另外一個整個阿里公認的超級技術大神:多隆。

一開始看到各種故障的時候,壓根就不知道怎麼下手,處理故障會需要的通常不僅僅是寫代碼的能力,還需要對一個系統全貌要有一定的掌握,例如前幾年一篇特別火的文章,當點擊搜索背後發生了什麼這樣的文章,其實就是要對一個系統的處理流程特別的熟悉,這在處理故障的時候是非常重要的,在有了故障大概在哪個環節後,很重要的就是對這個環節代碼運行機制的細節掌控了,這個時候通常來說各種工具非常重要,可以有效的幫助你知道具體發生了什麼,例如像系統層面的 top -H 之類的, java 層面的 btrace 等等,都可以讓你根據運行情況去定位問題的點。

這段時間我覺得我的提升就是靠大量的練手,故障確實有點多,一開始就靠看人怎麼處理,主要是從多隆這裏學,然後是嘗試自己解決一些故障,解決<typo id="typo-1414" data-origin="的" ignoretag="true">的</typo>越來越多後慢慢熟練度就上去了,除了解決故障能力的提升外,因爲看了很多由於代碼層面造成的故障,對自己在寫代碼時如何更好的保證魯棒性,來避免故障,是非常有幫助的,例如,我看過很多濫用線程池造成創建了大量線程,最終導致線程創建不出來的 case,就會明白自己在用線程池的場景裏一定要非常清楚<typo id="typo-1557" data-origin="的" ignoretag="true">的</typo>控制最大的數量,包括堆積的策略等,又例如我看過 N 多的因爲自增長容量的數據結構導致的 OOM 的 case,就會明白在寫代碼的時候不能認爲一定不會發生數據結構增長到超級大,所以不做任何保護的 case,這個時間我明白到的就是寫一段能運轉,實現需求的代碼不難,但要寫一段在各種情況下都能長期穩定運行的代碼是真心不容易,這我覺得是一個職業的寫商業系統的程序員和只是寫程序玩玩的最大差別。

第三段:重寫通信框架

2010 年,我從中間件團隊離開,去做 HBase,那個時候的 HBase 裏面的通信還是用一個非常簡單的寫法實現的,我想着要麼就把以前 HSF 裏用的移植到 HBase 裏用,這個時候剛好多隆在用 c 給各類 c 的應用寫一個通用的通信框架 libeasy,於是就有了一次測試,我記得第一次測試結果看到原來 HSF 裏面的通信框架的高併發能力和 libeasy 比相差無比巨大,我和多隆便探討他是怎麼實現的,我看看能不能學習下在 Java 這邊的版本里也改改,所以有了這段重寫通信框架的經歷。

本來以爲之前在寫 HSF 的那幾年應該算是對通信框架這塊的代碼相關的能力掌握<typo id="typo-2051" data-origin="的" ignoretag="true">的</typo>不錯了,在和多隆一起重寫的這段過程中,才發現差距還是很大的,多隆教會了很多細節的問題,基於 NIO 的通信框架的核心是用非常少的 IO 線程來處理 IO 事件(太多也沒用,因爲有些部分就只能串行),所以怎麼高效<typo id="typo-2157" data-origin="的" ignoretag="true">的</typo>使用好這幾個 IO 線程是非常關鍵的,要儘量減少這幾個 IO 線程處理一些不相關的動作,另外一點就是儘量減少 IO 線程和業務處理線程的切換,例如後來常見的批量把一個流裏的多個請求一次性丟給業務處理線程。

這段經歷對自己更加深入的掌握在代碼邏輯整體的細節層面是非常有幫助的,這對於寫要求很高的系統是非常重要的,畢竟對於一個超大規模的系統而言,1% 的提升還是可觀的。

第四段:學習 JVM

之前因爲處理故障比較多,有段時間我開始給公司同事們分享如何處理故障,後來發現有些問題自己也講不清楚,或者也不知道怎麼處理,必須深入學習 JVM 纔行,但其實一開始我完全摸不着門路,JVM 代碼打開都不知道從哪看起。

很幸運,碰到了一個同樣愛好又比我強很多的同學,就是撒迦,圈內通常叫 R 大,我和撒迦好幾個週末約着在公司一起看 JVM 代碼,有撒迦的指點,我終於是入門了,知道大概怎麼去看了,而且兩個人一起看代碼,互相分享和探討,效率是非常高的。

有了這段經歷,再加上繼續處理着一些故障,基本上逐漸對 JVM 的代碼實現有了更多的理解,在後來做故障分享、問題解決什麼的時候終於能更好的做到知其然知所以然,同樣,這對處理故障的能力,寫代碼的能力也是非常有幫助的,例如會更加明白以前認爲的所謂的面向 GC 友好的代碼是幾個意思,也會有了更深的感受是其實 Java 的代碼呢,通常不會寫的太爛,因爲 JVM 在運行期會做很多的儘可能的優化,拉到一個平均線,但要寫的很好,難度是非常大的,因爲需要懂 JVM,懂 JVM 下面的 OS。

總結

其實也總結不出什麼,因爲每個人的環境什麼的不太一樣,也有適合各自提升的方法,我看自己的經歷呢,我覺得:

  • 如果環境不具備,就給自己一個挑戰的命題,例如要學高併發的通信,可以嘗試自己寫一個和其他的做對比,做性能等的 pk,這個通常提升還是會很大的,要學 GC,可以嘗試給自己幾個題目,來控制 GC 的行爲等,如果環境具備的話,確實會更加有利。* 多和優秀的程序員一起,我自己從多隆、撒迦身上學習到了很多很多,從很多優秀的開源代碼,像 Netty,OpenJDK 裏面也學習到了很多很多,所以多參與一些優秀的開源項目也是一個很好的提升方法,看優秀的書(例如併發裏的那本 Java 併發編程實戰,JVM 裏的 Oracle JRockit: The Definitive Guide,深入理解 Java 虛擬機等),也同樣是一種向優秀程序員學習的好方法。* 多多嘗試解決問題/故障,這絕對是提升代碼綜合能力非常好的一個方法,自己工作裏機會少的話,網上有大把,像 stackoverflow 之類的,都是很好的練習場。

最後的最後,我還是想說,代碼能力作爲程序員的硬名片,始終是最有效的區分程序員能力的東西,"talk is cheap, show me the code" 這句話我覺得是永遠成立的。

作者:畢玄

本文爲阿里雲原創內容,未經允許不得轉載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章