精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

WhatsApp的架構是如何應付高流量的

責任編輯:一三

2014-04-08 09:16:23

摘自:CSDN

然而時過境遷,兩年后WhatsApp又是如何支撐10倍于之前的流量,以及應用的飛速擴展,這里我們一起看Tod帶來的總結。

【編者按】在之前我們有分享過HighScalability創始人Tod Hoff總結的WhatsApp早期架構,其中包括了大量的Erlang優化來支撐單服務器200萬并發連接,以及如何支撐所有類型的手機并提供一個完美的用戶體驗。然而時過境遷,兩年后WhatsApp又是如何支撐10倍于之前的流量,以及應用的飛速擴展,這里我們一起看Tod帶來的總結。以下為譯文:

兩年內的飛躍

天價應用當下的規模顯然不能與兩年前同日而語,這里總結了一些WhatsApp兩年內發生的主要變化:

1. 從任何維度上都可以看到WhatsApp的巨變,但是工程師的數量卻一直未變。當下,WhatsApp有更多的主機、更多的數據中心、更多的內存、更多的用戶以及更多的擴展性問題,然而最引以為豪的卻是那支10人工程團隊——每個工程師平均負責4000萬個用戶。當然,這也是云時代的勝利:工程師只負責軟件的開發,網絡、硬件及數據中心運維全部假手于人。

2. 在之前,面對負載的激增,他們必須讓單服務器支撐盡可能多的連接數,但是現在他們已經步出了那個時代。當然,基于總體成本的控制,他們仍然需要控制主機的數量并讓SMP主機更效率的運行。

3. 瞬時的好處。鑒于現在的架構已經囊括多媒體、圖片、文本、音頻,無需保存這些大體積格式的信息讓系統大大的簡化,架構的重心被放在吞吐量、緩存以及分片等。

4. Erlang的世界。即使他們打造的仍然是一個分布式系統,遇見的問題也大同小異,但是從始至終都在說Erlang確實值得稱道。

5. Mnesia,這個Erlang數據庫似乎已成為他們問題的主要來源。因此,不得不懷疑一味的緊抓Erlang會不會比較盲目,是否有其他更好的替代方案。

6. 如此規模下問題之多你可以想象。海量連接數的保持、隊列因優先級操作變得太長、計時器、不同負載下的代碼表現問題、高負載下高優先級消息得不到處理、一個操作被另一個操作意外打斷、故障導致的資源問題以及不同用戶平臺的兼容性等,巨型架構的打造絕非一朝一夕。

7. Rick的發現和處理問題能力讓人贊嘆,也可以說是吃驚。

Rick的分享總是非常精彩,他樂于分享許多細節,其中有許多只能在生產環境出現。下面是他 最新分享總結:

統計

月4.65億用戶

平均每日接收190億消息,發送400億消息

6億張圖片,2億條語音,1億段視頻

峰值期間1.47億的并發連接數——電話連接到系統

峰值期間每秒23萬次登陸操作——手機上線及下線

峰值期間每秒32.4萬信息流入,71.2萬的流出

約10個工程師致力于Erlang,他們肩負了開發與運維

節日的峰值

平安夜流出達146 Gb/s,相當多的帶寬用于服務手機

平安夜視頻下載達3.6億次

新年夜圖片下載約20億(46 k/s)

新年夜有張圖片下載了3200萬次

堆棧

Erlang R16B01(打了自己的補丁)

FreeBSD 9.2

Mnesia(數據庫)

Yaws

使用了SoftLayer云服務和實體服務器

硬件

大約550個服務器+備份

150個左右的Chat服務器(每個服務器處理大約100萬的手機、峰值期間1.5億的連接)

250個左右的多媒體信息服務器

2x2690v2 Ivy Bridge 10-core(總計40的超線程技術)

數據庫節點擁有512GB的內存

標準計算節點搭載64GB內存

SSD主要用于可靠性,存儲資源不足時還用于存儲視頻

Dual-link GigE x2(公共的面向用戶,私有的用于后端系統)

Erlang系統使用的核心超過1.1萬個

系統概況

獨愛Erlang

非常棒的語言,適合小工程團隊。

非常棒的SMP可擴展性。可以運行高配的主機,并且有益于減少節點。運維復雜性只與節點數有關,而不是核心數。

可以飛快的更新代碼。

擴展性就像掃雷,但是他們總可以在問題爆發之前發現并解決。世界級事件相當于做系統的壓力測試,特別是足球賽,會帶來非常高的峰值。服務器故障(通常是內存)、網絡故障以及差的軟件的推送都考驗著系統。

傳統的架構

手機客戶端連接到MMS(多媒體)

Chat連接到瞬態離線存儲,用戶之間的消息傳輸通過后端系統控制。

Chat連接到數據庫,比如Account、Profile、Push、Group等。

發送到手機的消息

文本消息

通知:群組消息,個人簡介照片改變等

狀態消息:輸入狀態、離開狀態、在線或離線情況等

多媒體數據庫

內存Mnesia數據庫使用大約2TB的RAM,跨16個分片存儲180億條記錄。

只存儲正在發布的消息和多媒體,但是在多媒體發布時,會將信息儲存在數據庫中。

當下單服務器只運行100萬的并發連接,而在兩年前這個數字是200萬,因為現在服務器要做的事情更多了:

隨著用戶量的增多,WhatsApp期望每個服務器上預留更多的空間以應對峰值。

許多過去不是運行在這個服務器上的功能現在被移到上面,因此服務器更忙了。

解耦

隔離瓶頸,讓之不會存在整個系統中

緊耦合會導致相繼故障

前端系統和后端系統首先要分離

隔離一切,讓組件間不會存在影響。

正在解決問題時,保持盡可能多的吞吐量。

異步處理以最小化吞吐量延時

當延時不可預知及在不同點存在時,異步可以盡可能的保證吞吐量。

解耦可以讓系統運行盡可能的快。

避免HOL阻塞

線頭阻塞是首位處理會餓死隊列中其他項目。

分離讀和寫隊列。特別是在表格上執行事務,寫入方面的延時不會影響讀取隊列,通常情況下讀的速度會很快,因此任何阻塞都會影響讀性能。

分離節點內部隊列。如果節點或者網絡連接的節點出現問題,它可能會阻塞應用程序中其他任務。因此,發往不同節點的消息會分配不同的進程(Erlang中的輕量級并發),因此只有當消息發送給問題節點時才會做備份,這將允許消息自由的傳輸,問題被隔離開來,給Mnesia打補丁以保證async_dirty級響應時間。App發送消息后就會被解耦,因此當一個節點發生故障時,不會導致負載問題。

在不確定延時場景下使用FIFO模型。

Meta Custering

本節出現在講話的第29分鐘,不幸但是,信息量不大。

需要一種方法來控制單集群體積,并允許他跨很長距離。

建立wandist,基于gen_tcp的分布式傳輸,由許多需要相互通信的節點組成。

1個基于pg2的透明路由層,建立一個單跳路由調度系統。

舉個例子:兩個數據中心的兩個主集群,位于兩個不同數據中心的兩個多媒體集群,以及兩個數據中心間一個共享的全局集群,他們之間都使用wandist進行連接。

例子

使用async_dirty來避免Mnesia事務耦合,大部分情況下不會使用事務。

只在從數據庫中恢復時才使用call,其他情況下都使用cast來維持異步模型。在Erlang,消息隊列會因等待handle_call響應而造成阻塞,handle_cast不會造成阻塞是因為它不關注結果。

Call使用超時而不是監視,減少遠端進程競爭以及分發時傳輸的數據。

如果只是想追求最好的交付能力,為cast使用nosuspend。這樣會阻止節點受到下游問題影響——不管是節點失敗還是網絡問題(在這些情況下,發送數據緩沖池會備份到發送節點上),進程發送的開始指令會被調度系統掛起,從而造成了相繼故障——大家都在等待,卻沒有操作正在被處理。

使用大的發送緩沖器,從而降低收來自網絡和下游系統的影響。

并行

任務分配

需要在1.1萬個核心上分配任務

始于單線程的gen_server,然后建立了一個gen_factory負責多節點之間的任務傳遞。

在負載達到了一定程度,調度過程本身就變成了瓶頸,不僅僅是執行時間問題。

因此建立一個gen_industry,位于gen_factory之上,從而并行的攝入所有輸入,并且有能力立刻給工作節點分配。

工作節點的尋址類似數據庫通過key查找,因此這里存在不確定延時,比如IO,所以為了避免線頭阻塞,這里使用了一個FIFO模型。

分割服務

在2到32間進行分割,大部分服務都被分割成32個。

pg2 addressing,分布式進程組,用于集群上的分片尋址。

節點進行主從設置,用于容災。

限制訪問單ets或者mnesia進程的數量到8,這會讓鎖爭用處于控制當中。

Mnesia

因為沒有使用事務去保證一致性,他們使用一個進程對一個節點上的記錄進行連續訪問。哈希到一個分片,會映射到1個mnesia fragment,最后會被調度到1個factory,隨后是節點。因此,對每個單記錄的訪問都會被轉換成一個獨立的Erlang進程。

每個mnesia fragment都只能在1個節點上的應用程序等級進行讀取,這樣復制流只需要在一處進行。

一旦節點間存在復制流,分片的更新速度上就會存在瓶頸。他們給OTP打補丁以實現多個事務管理器,用以實現async_dirty,從而記錄可以并行的進行修改,這將產生更多的吞吐量。

打補丁允許Mnesia庫直接被分割到多個庫上,這就意味著它可以寫多個驅動,這么做可以直接提升磁盤的吞吐量。這里存在的問題是Mnesia達到峰值,通過多個磁盤來分攤IO,而為了進一步提升可擴展性及性能,甚至會加入SSD。

將Mnesia“island”縮減到2個,每個“island”都是一個Mnesia集群。因此在表格被分割成32份時,將會有16個“island”支撐一個表格。從而,他們可以進行更好的schema operation,因為只需要修改兩個節點。在同時打開1或2個節點時,可以減少加載時間。

通過設置警報快速處理Mnesia中的網絡分片,讓它們繼續保持運行,然后手動的調節將它們整合。

優化

在峰值情況下,離線存儲系統曾是1個非常大的瓶頸,無法更快的將消息推送到系統。

每條消息都被用戶快速的讀取,60秒內完成50%。

添加一個回寫緩存,這樣消息就可以在寫入文件系統之前被交付,緩存命中率達98%。

如果IO系統因為負載而阻塞,緩存會對消息交付起到額外的緩沖作用,直到IO系統恢復。

給BEAM(Erlang VM打補丁)以實現異步文件IO來避免線頭阻塞問題,在所有異步工作線程上輪訓文件系統端口請求,在大型mailbox和緩慢磁盤的情況下可以緩解寫入。

讓大型的mailbox遠離緩存,有些用戶加入了大量的組,每小時收入數千消息。他們會影響整個緩存,并讓處理變慢。將它從緩存中驅除。需要注意的是,不成比例的大型用戶處理是每個系統都存在的問題,其中包括Twitter。

使用大量的fragments降低mnesia表格的訪問速度

賬戶表格被分割成512份打入“island”,這就意味著用戶和這512個分片間存在一個稀疏映射,大部分的fragments都是空的和空閑的。

主機數量翻倍,但是吞吐量降低。記錄訪問變慢的原因是當目標為7時,哈希鏈的大小超過了2K。

這里存在的一個問題是哈希模式會導致建立大量的空bucket,有些甚至會非常長。雙線的變化解決了這個問題,并將性能從4提升到1。

補丁

計時器輪上的競爭,當1個主機的連接數達到幾百萬,同時每個鏈接上的手機發生變化時就會建立或重置計時器,從而導致了每秒數十萬的計時器。計時器輪上的鎖則是競爭的主要來源,解決方法就是建立多個計時器輪。

mnesia_tm是個非常大的選擇循環,因此雖然負載未滿,也可能會造成事務的積壓,打補丁以收取事務流并且保存以作稍后處理。

添加多個mnesia_tm async_dirty發送者

存在許多的跨集群操作,因此mnesia最好從附近的節點加載。

給異步文件IO加入循環調度。

使用ets哈希開防止w/ phash2的同時發生。

優化ets main/name table來應對規模

不要隊列mnesia dump,因為隊列中存在太多的dumps時,schema ops將不可行。

2月22日的停機

即使做了如此多的努力,停機仍然不可避免,而且發生在了最不應該發生的時候,在被Facebook收購后宕機了210分鐘。

負載的變化導致了問題的發生,此次宕機歸結于后端系統的路由問題。

路由器造成了一片局域網的癱瘓,造成了集群中大量節點的斷開和重連。同時,在節點重連之后,集群出現了前所未有的不穩定狀態。

最終,他們不得不停機修復,這種情況在幾年內都未出現過。

在檢查中,他們發現了一個過度耦合的子系統。在斷開和重連時,他們發現pg2在做n^3的消息,消息隊列在數秒鐘內從0飆升到了400萬,為此他們推出了1個補丁。

特性發布

無法模擬如此規模的流量,特別是高峰期間,比如新年的鐘聲。因此,他們只能緩慢的發布特性,先在小流量下發布,然后迅速迭代直到良好運行,接著再向其他的集群推廣。

上線是一個滾動的更新過程。冗余一切,如果他們想做一個BEAM更新,在安裝后他們需要一個個的重啟集群中的節點然后更新。也存在熱補丁的情況,但是很罕見,通常的升級都非常麻煩。

鏈接已復制,快去分享吧

企業網版權所有?2010-2024 京ICP備09108050號-6京公網安備 11010502049343號

  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 拜泉县| 淮滨县| 丹巴县| 宁德市| 兴城市| 田林县| 眉山市| 新竹县| 巴中市| 九龙城区| 龙井市| 江达县| 英吉沙县| 黄大仙区| 青田县| 定兴县| 和田市| 五莲县| 石嘴山市| 彭州市| 连城县| 清远市| 子长县| 苏尼特右旗| 湘西| 秦皇岛市| 故城县| 黔南| 瓦房店市| 九江县| 大连市| 博客| 固原市| 和顺县| 谢通门县| 思茅市| 安徽省| 古浪县| 乐安县| 大渡口区| 石嘴山市|