談談Facebook的聊天系統架構

今天看到一份 Facebook 公司 2009 年的 Slideshow, 介紹它的聊天系統架構, 其中的一張圖結構非常清晰, 所以我對這張圖談談我的看法.

Web Tier: 用 PHP 開發, 聊天相關的業務邏輯代碼. 如 AJAX 請求, HTML 頁面拼接等. 這個模塊整個其它的 3 個模塊, 向瀏覽器提供了大部分的聊天接口.

Chatlogger, 用 C++ 開發, 消息的存儲服務. 至少向 Web Tier 層提供了消息保存, 聊天曆史消息, 最近聯繫人等基礎服務接口.

Presence, 用 C++ 開發, 提供用戶在線狀態維護服務. 這些服務器會將在線的用戶(UID)保存在內存中, 然後接受 Web Tier 的請求, 例如判斷某個用戶是否在線.

Channel(Comet) Cluster, 用 Erlang 開發, 提供基於瀏覽器的"Server Push(服務器推)"功能. 是對開源的 Mochiweb 的二次開發. 瀏覽器會跟 Channel Clusters 進行連接, 當 Web Tier 收到某個用戶的消息時, 會通過 Channel Cluster 推送到接收者, 實現網頁實時聊天功能.

關於 Web Tier, 其實沒有太多的技術可討論, 因爲這主要是業務邏輯, 即使不用 PHP 語言, 用 Python 或者 Java 等都沒有問題.

Chatlogger 雖然名字是"日誌記錄", 但它不可能是簡單的日誌記錄, 它必須要提供基本的消息服務接口. 而且, 爲了存儲數億 Facebook 用戶的聊天曆史, 必然要涉及到海量數據存儲. 這部分 Facebook 曾經用 Cassandra, 後來改爲 HBase. Chatlogger 使用 C++ 進行開發是基於性能的考慮, 而且消息存儲服務的接口比較固定, 不太可能經常變化.

Presence 維護用戶的在線狀態, 類似這種服務在網遊中比較常見. Presence 服務器使用 C++ 來開發, 也是基於性能的考慮. 如果使用 HTTP + PHP + Memcache/Redis 這樣的架構, 一是 PHP 代碼執行性能損失很大, 二是 Memcache/Redis 是通用的存儲方案, 不適合 Presence 的高性能需求. Presence 在數據全部保存在內存中, 速度快, 設計靈活. 注意, Presence 是一個被動服務器, 它並不主動向外推送消息, 這使得這樣的服務器接口非常固定, 獨立性很強. Presence 的數據主要來自於 Comet 羣集的推送.

Channel(Comet) Cluster 和瀏覽器保持網絡連接. Comet 有通道的概念, 每個用戶對應一個通道, 用戶會分佈在不同的服務器上, 用戶每打開一個新的瀏覽器標籤, 就會同服務器建立一個新的網絡連接, 但都是連到同一個通道. Comet 服務器是基於開源的 Erlang 服務器 Mochiweb 進行二次開發. 在身份驗證和安全方面, 通道的建立是由 Web Tier 進行控制的, 這樣如果用戶沒有在業務邏輯層經過相應的驗證, 就直接連接 Comet 服務器, 它是會被拒絕的. 另外, Comet 服務器會在自己的內存中先維護一份在線用戶列表, 然後定期更新到 Presence 服務器, 這也是二次開發的原因. 如果 Comet 服務器不自己先緩存一份在線用戶列表, 那麼用戶頻繁上線下線都立即通知 Presence 的話, 壓力會非常大.

架構已經很清晰, 但要應用起來, 代碼的開發是必不可少的. 當然, 不同的技術團隊會根據技術情況進行取捨. 例如消息存儲使用 MySQL, Presence 使用基於 Web 容器架構的技術來開發, 而 Comet 模塊可以使用 nginx-push-stream. 不過, 僅僅依靠整合開源系統而不做二次開發, 不可能解決大問題.

PDF 文件可以在這裏下載: http://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf


發佈了114 篇原創文章 · 獲贊 15 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章