架構師接龍:盛大許式偉VS. 金山張宴
主持人:馮大輝,現任丁香園 (http://www.dxy.cn)網站CTO。曾歷任支付寶架構師、資料庫團隊負責人等職。
許式偉:作為系統架構師,您一般會從哪些方面來保證網站的高可用性(降低故障時間)?
張宴:很多因素都會導致網站發生故障,從而影響網站的高可用性,比如伺服器硬體故障、軟體系統故障、IDC機房故障、程式上線前測試未發現的Bug、遭受分散式攻擊、突發訪問人數劇增等。
一套良好的網站系統架構,應該儘可能地避免只有一臺伺服器、一個數據庫、一套軟體節點等單點故障的存在。單點故障一旦發生,將直接導致網站服務不可 用,恢復正常服務所需的時間也比較長,甚至還可能無法恢復。負載均衡叢集、雙節點熱備、分散式處理等都可以用來解決單點故障,比如提供相同業務的Web服 務器、MySQL資料庫從庫,都可以構建負載均衡叢集。一旦叢集中的一臺伺服器、一個服務出現故障,自動實時摘除,對使用者來說是不可感知的,不會影響到整 個網站的訪問,可以為運維工程師留下足夠的時間去排查和解決故障。
對於重要的MySQL資料庫主庫,我們習慣於從硬體層和軟體層來實現熱備,避免單點。越 是複雜的裝置,發生故障的概率越大。在磁碟沒有損壞的情況下,應用程式導致伺服器宕機的概率,遠高於簡單的磁碟陣列宕機的概率。所以,從硬體層解決的話, 可以在兩臺伺服器上安裝相同的資料庫版本、進行相同的配置,用SAS或SCSI線連線一臺磁碟陣列,將資料庫資料檔案存放到盤陣上。正常情況下用伺服器A 掛載盤陣分割槽,啟動MySQL,繫結虛擬IP;如果伺服器A宕機,則用伺服器B掛載盤陣分割槽,啟動MySQL,接管虛擬IP。從軟體層解決的話,則可以借 助DRBD等軟體做映象。
IDC機房發生故障的概率較小,但如果發生的話,影響面也是最大的。如果所有伺服器都託管在一個IDC機房,一旦該機房遭遇長時間流量攻擊、斷電、 斷網、地方政策性封網等,通常只能聯絡IDC去處理,除此之外束手無策,解決時間也比較長。如果成本允許,將網站伺服器分佈在兩個以上的IDC機房,當某 個IDC發生故障時,可以臨時切換DNS域名解析來優先恢復服務。
雖然程式程式碼上線前,經過了測試人員的嚴格測試,但測試環境和生產環境畢竟有差異,所以一些會急劇影響效能、正常服務的Bug往往在程式上線之後, 才會被發現,這就要求我們在發現Bug後,能夠迅速回滾到上一正常版本。我們在SVN的基礎上,開發了Web程式碼釋出系統,會將每個釋出版本之間的檔案變 更記錄下來,一鍵實現程式程式碼在多臺Web伺服器上的釋出和回滾。
遭遇DDOS分散式拒絕服務攻擊,使用防火牆來對付半連線、假IP,還算比較容易。而那種專挑複雜動態應用程式URL進行的分散式CC攻擊,來源為 真實IP、真實HTTP請求,具有模擬正規瀏覽器User-Agent、單個IP的每秒請求數不高、有成千上萬個攻擊源等特徵,很難與正常訪問區分開,比 較難對付。但是,正常通過瀏覽器訪問一個URL,會載入該URL中引入的JavaScript指令碼、CSS樣式、圖片等檔案。遇到CC攻擊,需要及時分析 日誌,找出訪問量異常上漲的URL,然後用事先寫好的shell指令碼找出哪些IP的請求只訪問了該URL,而不載入該URL引入的檔案,對這些IP進行自 動封鎖。
系統架構設計時,需要事先考慮到高於目前訪問量多少倍的突發訪問。對於網遊站點來說,訪問量受廣告集中時間段投放、線上活動的影響較大,頻寬峰值時 間不固定,對於靜態內容,可以使用商業CDN,按實際使用量計費。對於動態內容,如果遇到突發訪問人數劇增,超過現有伺服器處理能力,最簡單的臨時處理辦 法就是增加伺服器。上架新伺服器需要時間,但是,同一個IDC機房內,可以藉助其他業務的伺服器,在不同埠開啟一組新程序,加入到原有負載均衡池中。另 外,可以臨時關閉一些Web中的次要功能,來減少伺服器消耗。
許式偉:您在任務切分上,有什麼經驗分享?您通過哪些手段保證任務的獨立性?
張宴:相信很多人都遇到過這種情況:在一個老專案上修改、增加一些新功能所花費的時間,不比重新來做一個包含所 有功能的新專案時間用得少。一個需要長期維護的專案,不可避免地會面臨老員工的離職、新員工的接手,很多時候,專案程式碼的可維護性將決定一個專案的生存周 期。讓一個新員工在規定開發時間的壓力下,去面對一個文件不夠詳細、陌生的、功能複雜的龐大專案,短時間弄明白所有功能邏輯不是一件容易的事。所以,任務 需要切分,將一個大的任務切分成一個個小模組之後,各模組之間可以做到程式碼獨立,互不影響,可維護性也大大增強。
關於任務切分,我以本人今年負責的兩個重要專案架構設計為例來介紹一下。在第一個專案:金山遊戲官網的《使用者行為分析系統》中,由於資料探勘計算需 要消耗較高的記憶體、CPU資源,一臺伺服器的處理能力不夠,而商業的分散式資料倉庫價格又太貴,所以,只有從程式應用中下手,進行任務切分。我們先按需要 挖掘的資料指標,將整個資料探勘任務切分成多個數據挖掘外掛,每個外掛可以在不同的伺服器上執行,多個外掛可以同時在多臺伺服器上。多個數據挖掘外掛之 間,如果用到相同的某項資料,那麼,就將該項資料以冗餘方式,複製幾份提供給需要的外掛,從而實現外掛之間無互動、無關聯,保證了超大資料量下外掛的運算 速度。
在第二個專案:金山遊戲新版運營管理系統中,則將整個任務切分成了PHP Web管理介面、PHP Web API功能介面、C/C++中介軟體引擎三部分。這是一種分層結構切分,最上層的“PHP Web管理介面”呼叫“PHP Web API功能介面”,“PHP Web API功能介面”呼叫執行在遊戲伺服器端的“C/C++中介軟體引擎”,“C/C++中介軟體引擎”與“遊戲伺服器端程序”通過TCP、UDP二進位制協議、信 號、命令列等多種方式通訊。四者之間相對獨立,程式碼無關聯,通過一層層API介面實現互動。“PHP Web管理介面”負責通用介面實現。“PHP Web API功能介面”內部,又按接入的遊戲模組、子功能模組進行了更細的切分,各功能模組之間通過內部API互動。“C/C++中介軟體引擎”大而全,不處理具 體指令,但相容TCP、UDP、HTTP、HTTPS/SSL、訊號、命令列等大多數通訊方式,負責和各種型別的遊戲服務端互動。這是一套完全由API接 口驅動的系統架構,一款新遊戲接入運營管理系統時,只需在“PHP Web API功能介面”中增加一個模組;一個遊戲新管理功能的增加,只需要在“PHP Web API功能介面”中增加一個子模組。通過任務切分,將複雜功能簡單化,也將原來接入一款新遊戲所需要的幾個月時間,縮短為1~2周。
許式偉:您通過哪些手段,來保障產品的質量?您傾向於多久更新一次您的網站?
張宴:Web產品質量主要體現在架構、功能、效能、安全、程式碼唯一性、相容性等方面。
架構方面,我會先設計一套架構方案,然後讓和專案相關的人員、專家組成員參與進來,一起探討和論證架構的利弊,提出改進意見,保證架構的可行性。所有重要專案的技術方案需要經過專家組的評估。
功能、效能方面,則會由專門的測試人員進行功能測試、壓力測試、安全掃描,測試環境分為線下測試環境、線上準測試環境。
在程式碼唯一性方面,我們開發了一個Web配置資訊管理平臺及相關PHP擴充套件,提供給系統工程師,用於配置資訊的統一管理。在新專案中,PHP程式配 置檔案中將不再出現MySQL、Memcached等各類IP和埠資訊,統一用Web配置資訊管理平臺給出的變數代替。從“開發環境→線下測試環境→線 上測試環境→線上正式環境”,連線的資料庫各不相同,導致PHP開發工程師經常搞混淆或忘了修改,通過Web配置資訊管理平臺,使得PHP程式碼中的配置文 件,在四個環境中無須作任何修改,保證了程式碼的一致性,降低了出錯率,從而確保了產品質量。
在相容性方面,我們從作業系統到PHP、MySQL版本,都保持開發環境、測試環境、線上環境的統一,所有的Web服務執行在CentOS Linux系統上。由於大多數PHP程式設計師習慣於在Windows上編寫程式碼,而我們的程式中呼叫的一些介面、PHP擴充套件,只能在Linux下執行。為 此,我們開發了一個小工具,可以將多名程式設計師在各自本機Windows上搭建的nginx虛擬主機、編寫的程式檔案,對映到一臺Linux伺服器,用 Linux上的php-cgi執行Windows上的PHP程式碼。這樣,PHP程式設計師修改完本機程式碼,儲存一下,即可除錯,多人之間互不影響。自己除錯通 過後,可以在Windows直接點選滑鼠右鍵,將修改的程式碼提交到SVN版本庫。
Web 2.0時代,講究網站更新的實時性,動態網站不用說,靜態網站的內容釋出也要保證實時。我們開發了一款名為Sersync的開源軟體 (http://code.google.com/p/sersync/),使用Linux 2.6核心的inotify監控Linux檔案系統事件,被監聽目錄下如果有檔案發生修改,Sersync將通過核心自動捕獲到事件,並將該檔案利用 rsync同步到CDN源站伺服器。Sersync僅僅同步發生增、刪、改事件的單個檔案或目錄,不像rsync映象同步那樣需要比對雙方伺服器整個目錄 下數千萬的檔案,並且支援多執行緒同步,因此效率非常高。金山遊戲官網的CMS內容釋出系統,無論網站編輯通過Web還是FTP上傳圖片、視訊、附件,還是 系統工程師直接去CMS釋出伺服器上增加、修改、刪除檔案,幹完這些事情後不用做任何處理,Sersync 會自動將發生增、刪、改事件的檔案同步到CDN源站伺服器,並可以在檔案同步完成後,自動呼叫CDN快取重新整理介面,主動刷新發生修改、刪除的檔案的訪問 URL。
許式偉:您在面試時,通常關注應聘者的哪些方面?哪些問題經常會問呢?
張宴:第一,需要具備崗位要求的基礎技能知識,這方面我不再詳述。
第二,注重專案經驗與積累,不看重學歷與工作年限。做一個專案,猶如打一場戰役,身經百戰,積累下來的成功經驗可以讓工作更得心應手,失敗經驗可以避免走很多彎路。
第三,能夠在1~2個以上技術領域精通。所謂術業有專攻,能夠在某幾項技術領域做到精通的人,相信對於新的技術領域或者從未有過相關經驗的新專案,也能夠輕鬆勝任,做到盡善盡美。
第四,關注應聘者的知識廣度。如今的專案,已經告別個人英雄時代,講究團隊的協作。知識面越廣,儘管在非專攻領域的深度可能不夠,但是,知己知彼,可以站在一個更高的角度上看問題,這對於團隊協作開發、專案融合的益處是顯而易見的。
第五,具備良好的領悟能力、思考能力、設計能力、創新能力。基礎技能知識不夠可以學習,經驗不足可以積累,技術不精通可以鑽研,知識面不廣可以開 拓,但要培養這四項能力,是一件非常困難的事。要打造一支優秀的團隊,這四項能力不可缺少,它們的重要度甚至超過以上的四方面要求。
我不會經常去問固定的問題,但所問的問題,幾乎都跟以上的這些方面相關。
許式偉:您曾嘗試開放自己的程式程式碼嗎?您對中國國內開源社群的現狀有何看法?
張宴:是否開源自己的程式程式碼,跟所在公司或部門的性質有著密切的關係。如果是在研發驅動型企業或部門,程式代 碼是公司生存的命脈,需要與競爭對手拼技術和保持技術領先的優勢,因此,很難支援開源事業。反之,如果是在運營驅動型企業或部門,技術是用來提高運營質 量、運營水平的工具之一。將純粹的技術程式碼或產品,從公司的業務產品中提取出來,進行開
源,可以按照開源產品的要求,提高公司內部技術產品的規範化、標準化,還可以引用更廣大使用者的使用、反饋和意見,解決未發現的潛在Bug,改進程式碼質量, 提升技術水平。對於提高運營質量、運營水平來說,益處多多。我也嘗試開源自己的一些程式碼,例如簡單訊息佇列服務 HTTPSQS(http://code.google.com/p/httpsqs/)、MySQL HTTP/REST客戶端MySQL-UDF-HTTP(http://code.google.com/p/mysql-udf-http/),同時, 也鼓勵團隊成員嘗試開源,例如剛才提到的自動同步軟體Sersync。
國內的開源社群在不斷壯大,很多知名網際網路公司都開源了自己的一些產品,但大多數還只停留在開源產品的使用、技術交流、漢化層面,真正參與到開源產品編碼中的人還是較少,很多開源產品最終還是由原作者或原公司團隊維護。國內開源社群的道路仍然漫長。