Facebook 實時聊天架構日均處理數十億條消息
摘要:Facebook 的實時聊天架構每日可處理數十億條消息。
作者 | shivang
譯者 | 彎月,責編 | 郭芮
出品 | CSDN(ID:CSDNnews)
以下為譯文:
在這篇文章中,我將討論Facebook的實時聊天架構,該架構每天可以處理數十億條的消息。
Facebook的實時聊天架構後台使用了哪些技術?技術棧包括哪些?系統採用了怎樣的架構?像Facebook一般擁有如此大量用戶的平台在推出和擴展實時聊天功能時,主要面臨的難題有哪些?
下面就讓我們一起來看看吧。
引言
這一切都始於一場黑客馬拉松,當時一群Facebook工程師寫了一個聊天軟體的原型,並在他們的團隊面前進行了展示。雖然只有最基本的功能,但是浮動的聊天框可以在網頁上拖動,即便頁面重新載入和移動到其他頁面,該聊天框依然會顯示。
Facebook的工程師採納了這個原型,然後將其發展成了全面的實時聊天功能,後來這就成了Facebook服務生態系統中使用最頻繁的功能之一。
該聊天軟體每天要處理全世界發送的數十億條消息。社交平台的工程團隊對其進行了良好地擴展,其響應時間不足100毫秒。
該功能不斷得到改進,其唯一的目的就在於為用戶提供一流的通信服務。
為什麼要從頭開始編寫和維護聊天功能?為什麼不集成第三方聊天服務?
除了基本的聊天功能外,Facebook的聊天模塊還集成了社交圖。用戶可以輕鬆地獲取他們的朋友列表,以及其他相關信息,比如他們正在玩的遊戲和瀏覽的內容。
通常,平台上用戶可用的所有信息也可以在聊天模塊上訪問。
與集成第三方代碼相比,從頭編寫聊天功能更容易、更清晰、更安全且可以提供更多控制。
實時聊天架構與技術棧
Facebook聊天軟體的整個系統由幾個鬆散耦合的模塊組成,這些模塊彼此協同工作,例如Web層、用戶界面、聊天記錄、用戶上線模塊和頻道集群。
用戶界面
用戶界面自然是用JavaScript編寫的,也利用PHP做了伺服器端渲染。
客戶端和伺服器之間通過Ajax建立長期的持久連接。
該框架沒有採用Flash的原因主要有兩個:首先,使用Flash就會要求用戶在瀏覽器中安裝插件,這種用戶體驗不佳;其次,從安全形度來看,Flash不是首選。
消息獲取流程採用了基於HTTP模型的PULL與PUSH相結合。
最初,客戶端需要發送PULL請求以獲取消息的第一個快照,這一步會同時執行訂閱操作(這是基於PUSH的方法)。
在用戶訂閱了更新之後,只要有新的更新,Facebook後台就會將更新推送到客戶端。
後台Web層
Web層由PHP提供,處理Web請求本身。負責用戶身份認證、朋友的隱私設置、聊天記錄、朋友更新以及其他平台功能業務邏輯。
用戶在線狀態模塊
該模塊提供用戶朋友的在線信息。該模塊採用C++編寫,是系統中最常用的模塊。
該模塊聚合了內存中用戶的在線信息,並在請求時將信息發送給客戶端。
頻道伺服器
頻道伺服器負責消息隊列和傳遞。該功能採用Erlang編寫。
Erlang是一種並髮式函數編程語言,可用於編寫即時消息、金融科技、在線電話等實時的可擴展和高可用性系統。
Erlang的運行時系統內置並發、分發和容錯的支持。
頻道伺服器利用了Mochi Web庫。這是一個用於構建輕量級HTTP伺服器的Erlang庫。用戶發送的消息會送到頻道伺服器的隊列中。每條消息都有一個序列號,可以保證兩個或多個用戶之間的同步通信。
聊天記錄
聊天記錄模塊可以記錄聊天的元數據以及其他信息。該模塊採用C++編寫,用於記錄UI頁面載入之間的信息。
服務的可擴展性和部署
Facebook所有數據中心都持有用戶上線與聊天記錄數據的副本,而頻道伺服器數據僅存儲在一個專用的數據中心,以確保消息的強一致性。
如上圖所示,所有後台模塊都採用鬆散耦合,各個模塊之間通過Thrift互相通信。
Thrift是一種通信協議,可用於在異構技術上運行的服務之間的通信。
它是Facebook內部開發的服務通信的序列化和RPC框架,有助於運行在C++、Erlang、PHP、JavaScript上的系統作為一個團隊協同工作。
資源密集度最高的操作
整個系統中資源密集度最高的操作不是發送數十億條消息,而是讓用戶掌握朋友的在線狀態。
這個功能非常重要,因為只有當一個人看到朋友在線才會開始對話。
為了實現這一點,一種選擇是向用戶發送朋友上線的通知。但考慮到Facebook平台的用戶數量,這種實現方式沒有可擴展性。
在最差的情況下,該操作的複雜度為O(用戶的平均朋友數 * 流量高峰期的用戶數 * 用戶離線和重新上線的頻率)個消息/秒。
在高峰時段,Facebook網站上的並發用戶數量高達數百萬。保證所有用戶的上線信息最新,這在技術上是不可行的。
此外,即便是沒有聊天的用戶通過後台的非同步輪詢獲得朋友的活動狀態也會給伺服器帶來巨大壓力。
為了實現可擴展的用戶在線狀態後台,頻道伺服器的集群會保留用戶的在線狀態,並通過定期批量更新將其發送到狀態伺服器。
這種方法的優點在於,只需一個查詢就可以獲取用戶朋友的整個列表。
考慮到模塊之間巨大的信息交換量,頻道伺服器會在將信息傳輸到狀態伺服器之前進行壓縮。
隨著用戶連接數越來越多,負載均衡器的數量也會增加。在此之後,基礎架構管理並發用戶連接的能力得到了顯著提高。這是一個瓶頸,會在高峰時段導致聊天服務發生中斷。
消息與存儲的同步
如前所述,為了管理同步通信,每條消息都有一個序列號。
除此之外,Facebook還創建了一個Messenger同步協議,將非媒體數據使用量減少了40%。這減少了網路擁塞,並擺脫了由此引起的錯誤。
Facebook的工程團隊編寫了一項名為Iris的服務,該服務可以將消息更新組織在有序隊列中。
該隊列具有不同的指針,可幫助跟蹤用戶已讀的消息以及尚未處理的消息更新。
最近的消息由Iris的內存發送,舊的會話從普通的存儲中獲取。Iris建立在MySQL和快閃記憶體之上。
最初,消息存儲採用了Hbase,但後來又遷移到了MyRocks。這是一個由Facebook開發的開源資料庫項目,以RocksDB為MySQL存儲引擎。
原文:https://www.8bitmen.com/facebook-real-time-chat-architecture-scaling-with-over-multi-billion-messages-daily/
本文為 CSDN 翻譯,轉載請註明來源出處。
【END】


※喬納森離開蘋果;李彥宏被潑水;Windows 公開 Linux 內核源代碼 | 開發者周刊
※徹底火了!這份Python學習貼,90%程序員用的上
TAG:CSDN |