如何解讀《微信技術總監談架構:微信之道——大道至簡》

guojin08發表於2018-03-20
[http://www.52im.net/thread-201-1-1.html]學習一下

一、前言


最近在朋友圈看到有人分享騰訊微信技術總監周顥的一個技術報告,題目是《微信技術總監談架構:微信之道——大道至簡》(演講全文整理演講PPT講稿下載),我也轉發了一下。然後就被本司妹子看到了,非讓我解釋一下。

無奈微信的技術人員出來交流的太少了,只能寫下這篇淺顯的文章,通俗的解釋一下微信背後的技術力量。

二、敏捷


在微信的技術報告中,通篇演講所說的內容,其實都是為了兩個字服務:“敏捷”。首先,我們要先解釋一下敏捷。

在軟體領域,敏捷軟體開發實際上已經是一種術語,它又稱敏捷開發,是一種從1990年代開始逐漸引起廣泛關注的一些新型軟體開發方法,是一種應對快速變化的需求的一種軟體開發能力。敏捷 (Agile)也是一股思潮, 它包括了好幾種軟體開發的方法論 (methodology); 這些方法論又是建立在許多業界證明行之有效的最佳實踐方法 (best practices) 上面的,例如:Software Development Rhythms 、ASD/Adaptive Software Development、Scrum、XP Extreme Programming等等。敏捷開發最終的目的,都是使軟體能夠快速迭代和交付。

So,簡單來說就是為了軟體快速迭代和交付,微信的技術做了什麼事情,是如何做的。

在報告中,有一段話的意思是這樣的:微信的成功來源於產品決策的成功,為了給產品決策最大的自由度和能力,微信的技術允許釋出前十分鐘的需求變更。做到這個事情非常非常牛,我必須要解釋一下它的難度。

一個人的精力是有限的也是容易出錯的,所以,在傳統軟體開發流程中,規定了一系列的規範來保證軟體能夠不出錯。一個需求的完整開發流程大致是這樣的:需求提出,技術分析,開發,自測,模組測試,聯調測試,灰度測試,完整發布。

即使已經做了這麼多步的保證,所有故障的80%仍然是釋出導致的。為了保證服務的穩定性——微信的及格線是99.95%——開發中的變更一般是很昂貴的,因為需要把已經走過的步驟再重走一遍。所以大部分軟體開發對於開發中的需求變更都是非常忌諱的,對於開發人員來說也是如此,誰也不想辛苦完成的東西再重新來一遍,或者因為頻繁的需求變更導致測試不完全而出現故障。放張漫畫感受一下程式設計師的心情

如何解讀《微信技術總監談架構:微信之道——大道至簡》_4202b62de3222386d633d3ecd165fca1_r.jpg 

對於微信來說,更是如此。我估計微信內部有上百個模組,幾千臺伺服器,任意一個模組、程式出現問題都可能會影響到微信的正常服務。尤其是在釋出前十分鐘還允許變更,需要一套強大的技術、測試和監控系統才能支援如此的任性。

對比一下前東家(不能說名字,也算個大廠),固定每週釋出兩次,釋出持續時間4個小時。例如,週二釋出一次,那週二釋出的所有需求在週一上午已經確定了;如果釋出失敗了,第二天繼續發這個。我曾經見過有一個需求一週都沒有發上去。

在如此困難的情況下,微信憑藉了幾個思路來做到如此敏捷,後面我來依次解釋一下。

三、努力減少人為的錯誤


既然人的問題如此突出,那麼,要想提高效率做到敏捷,一定要先從人的方面著手。
微信的這篇報告提出的思路是:大系統小做+基礎元件。應該說,這是一個工業界普遍的解決思路。 

我們一般人看到的軟體,例如微信,就是在自己手機上執行的一個程式,無所謂大小系統,所有的功能都集中在一起,集中在一個軟體中,無需也不能拆分。但在這種服務類軟體例如微信、微博等,還有一個更加龐大在後端伺服器的程式。

第一,一般來說,後端服務的邏輯相對前端軟體來說更復雜:

後端程式要做各種計算、驗證和儲存的功能。如果前端軟體端的程式碼有幾萬行的話,後端服務的程式碼一般要有幾十萬或者上百萬行。例如,簡單的登入,在前端只不過發一個登入的請求到後端伺服器,而伺服器要做的事情呢,從資料庫中取得你的使用者名稱和密碼驗證資訊,把請求過來的使用者名稱加密密碼(密碼不能明文儲存,要經過一些複雜的計算過程取得一個加密的東西)和資料庫的進行驗證;判斷是否一個異常登入(還要從資料庫取的最近的登入資訊);判斷是否過頻繁登入(防止惡意伺服器攻擊);等這些都做完了,才能返回說登入成功了。

第二,伺服器端程式要比前端軟體層承載更多的請求和更大的壓力:

還是以上一點說的登入舉例,所有的那些操作,伺服器端要在100ms之內處理完成;同時,這種登入請求每一秒都有幾萬或者十幾萬。至少現在,一臺普通伺服器是無法同時處理這麼多請求的,這就表示後端程式要部署很多臺機器才行,這也造成了更多的複雜性。

如此複雜的系統,一個人是萬萬駕馭不了的。那麼,唯一的選擇就是把複雜變成簡單。

首先,針對邏輯複雜的特點,我們會把幾十萬行程式碼組成的系統進行拆分,拆分一般是依據功能性,例如:註冊登入、訊息邏輯、漂流瓶等等,然後把這些程式分別部署到不同的伺服器上。

放一頁報告的PPT:
如何解讀《微信技術總監談架構:微信之道——大道至簡》_a72f4f05f45afd0ece8535fcfd38a915_r.jpg

這張圖應該是微信伺服器端的主要邏輯和部署結構,其中每一個機器的圖都是一組(很多臺)伺服器。這樣的好處很明顯,當拆分後,一個人只需要瞭解其中某一個模組的程式即可,不再需要詳細的瞭解其他東西是怎麼執行的。

但是,邏輯的複雜性解決了,又出現了另外一個問題,就是遠端呼叫的複雜度和穩定性問題。

定義一下遠端呼叫(RPC):

In computer science, a remote procedure call (RPC) is an inter-process communication that allows a computer program to cause a subroutine or procedure to execute in another address space (commonly on another computer on a shared network) without the programmer explicitly coding the details for this remote interaction.


簡單來說,要呼叫的程式在另外一臺物理伺服器上。

而有網路參與的情況下,可靠性要比單機呼叫低一個等級,為了彌補這個可靠性的降低,需要做很多異常情況處理,例如:網路斷了、有一次呼叫非常慢,有一臺伺服器沒有響應了等等。

我們前面又提到,微信只有幾十上百個模組在同時執行,不能要求每一個模組都把這些複雜的東西都做一次,並且受限於經驗的問題,每個人做的都會不一樣會有遺漏,這個時候,遠端服務框架這個基礎元件就應運而生了。

在報告中的一頁PPT,提到了兩個基礎元件:

如何解讀《微信技術總監談架構:微信之道——大道至簡》_2e2a2d607eafc11bcc79a4bf7d65639d_r.jpg 

就是屬於遠端服務框架中的一部分,它能夠讓開發人員很簡單的使用,10分鐘即可寫一個遠端呼叫,並且各種錯誤都由框架處理了,只要很開心的關心我們的業務是如何執行的即可。Yes,開發快了好多倍。

當然,遠端服務框架是一個很複雜和系統的工程,他至少應該關心4個方面:

  • 開發的簡易型
  • 服務的分散式呼叫鏈及服務狀態的跟蹤統計
  • 服務的配置管理,包括服務發現、負載均衡和依賴管理
  • 服務之間的排程和生命週期管理

阿里巴巴公司曾經開源過一套遠端服務框架:dubbo,摘一張它的程式整體設計圖:

如何解讀《微信技術總監談架構:微信之道——大道至簡》_5b19b50d9ef5315b39ff4a3c50ab8788_r.jpg

在報告中還提到一個很重要的基礎元件,儲存元件,它遮蔽了容災擴容等複雜問題。

儲存是如此重要,所有的內容最終都要落到儲存上;儲存是如此重要,大部分的操作最終都要從儲存讀資料。正因為儲存的重要,所以它又顯的非常脆弱,任何一點小的問題,一定會影響一大批使用者。

在這種情況下,務必要進行減少儲存的出錯機率,並且讓上層遮蔽這些處理,讓開發人員專注於自己的模組,這種思想和前面說的遠端呼叫框架思路是一致的。

在報告中,提到了4中容災模型,前面兩種分別是主備、雙寫,這個就不多說了,主要說下另外兩種。

Set模型+雙寫:

如何解讀《微信技術總監談架構:微信之道——大道至簡》_59f2073038176eae708a3ea4228138e4_r.jpg 

這裡,報告裡說的不慎明確,他說能夠實現完全一致的備份副本,但是隻能支援追加寫以及需要外部索引,類似簡化版的GoogleFS,主要儲存圖片和音訊。這裡我腦補一下,希望能猜中。

讀到這些關鍵字,除了GoogleFS,我還想起了一個東西:bitcask模型。

如何解讀《微信技術總監談架構:微信之道——大道至簡》_QQ20160402-8.png 

bitcask模型有一個外部索引,一般是放到記憶體中,儲存了每一個key所在的檔案位置和value長度及位置;在寫入的時候,追加寫入檔案中,並更新索引內容,把位置指向新的磁碟位置。bitcask模型的好處是對於機械磁碟友好,寫吞吐量大,資料持久化好不用擔心crash後的資料丟失問題。這種模型就和報告所說的特點很像了,只不過把記憶體索引放到了外部一個單獨的服務裡面。當一個Set寫入失敗的時候,只需要寫入另外一個,並把索引寫入索引服務即可;讀的時候,先讀索引服務,然後去某一個Set中讀取資料。因為每一個Set都做了主備模型,並不特別擔心不可讀。

四、及時發現錯誤


說了這麼多,我們做了好多事情來儘量避免問題的產生,提高生產效率,但是遺憾的是,錯誤永遠不可避免,這個時候,能夠及時發現錯誤並解決它,影響儘量少的人就成了關鍵。微信給出的答案是:一套簡單易用的監控系統+自動報警+灰度上線

對於這個,我其實沒有啥好說的,都應該能很好的理解,任何軟體服務的監控工作都是必不可少的。不過聽視訊上說的,微信5分鐘即可部署好一個監控點並設定好報警閾值,完成監控和自動報警的工作,這個還是很牛的。

還有一項技術是灰度上線。顧名思義,灰度介於黑與白之間。在這裡的意義就是,上線時只上線一部分,目的是用一部分使用者檢測程式碼的正確性,如果出現異常可以迅速的回到之前正確的程式碼上,實現影響儘量少的使用者。

如何解讀《微信技術總監談架構:微信之道——大道至簡》_6af0e1780de6a5651d476b0b38fd0123_r.jpg

從報告給出的截圖看,微信可以實現上線時任意選擇要上線的伺服器。如果上線有問題,也只會影響到訪問到問題伺服器的使用者。當一臺伺服器上線驗證沒有問題,可以選擇多幾臺上線,最後再上線全部伺服器。這樣就減少了很多的風險,有更大的容錯性。

相關文章