自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

成人網(wǎng)站性能提升20倍之經(jīng)驗談

開發(fā) 前端 后端
要搞定這巨大的流量很難。更困難的是,在色情網(wǎng)站上提供的很多內(nèi)容都是低延遲的實時流媒體而不是簡單的靜態(tài)視頻。但是對于所有碰到過的挑戰(zhàn),我很少看到有搞定過它們的開發(fā)人員寫的東西。所以我決定把自己在這方面的經(jīng)驗寫出來。

色情業(yè)是個大行業(yè)?;ヂ?lián)網(wǎng)上沒有多少網(wǎng)站的流量能和最大的色情網(wǎng)站相匹敵。

搞定這巨大的流量很難。更困難的是,在色情網(wǎng)站上提供的很多內(nèi)容都是低延遲的實時流媒體而不是簡單的靜態(tài)視頻。但是對于所有碰到過的挑戰(zhàn),我很少看到有搞定過它們的開發(fā)人員寫的東西。所以我決定把自己在這方面的經(jīng)驗寫出來。 

問題是什么?

幾年前,我正在為當(dāng)時全世界訪問量排名26的網(wǎng)站工作 — 這里不是說的色情網(wǎng)站排名,而是全世界排名。

當(dāng)時,該網(wǎng)站通過RTMP(Real Time Messaging protocol)協(xié)議響應(yīng)對色情流媒體的請求。更具體地說,它使用了Adobe的FMS(Flash Media Server)技術(shù)為用戶提供實時流媒體?;具^程是這樣的:

  1. 用戶請求訪問某個實時流媒體
  2. 服務(wù)器通過一個RTMP session響應(yīng),播放請求的視頻片段

因為某些原因,F(xiàn)MS對我們并不是一個好的選擇,首先是它的成本,包括了購買以下兩者:

  1. 為每一臺運行FMS的服務(wù)器購買Windows的版權(quán)
  2. 大約4000美元一個的FMS特定版權(quán),由于我們的規(guī)模,我們必須購買的版權(quán)量數(shù)以百計,而且每天都在增加。

所有這些費用開始不斷累積。撇開成本不提,F(xiàn)MS也是一個比較挫的產(chǎn)品,特別是在它的功能方面(我過一會再詳細說這個問題)。所以我決定拋棄FMS,自己從頭開始寫一個自己的RTMP解析器。

最后,我終于把我們的服務(wù)效率提升了大約20倍。

開始

這里涉及到兩個核心問題:首先,RTMP和其他的Adobe協(xié)議及格式都不是開放的,這就很難使用它們。要是對文件格式都一無所知,你如何能對它進 行反向工程或者解析它呢?幸運的是,有一些反向工程的嘗試已經(jīng)在公開領(lǐng)域出現(xiàn)了(并不是Adobe出品的,而是osflash.org,它破解了一些協(xié) 議),我們的工作就是基于這些成果。

注:Adobe后來發(fā)布了所謂的“規(guī)格說明書”,比起在非Adobe提供的反向工程wiki和文檔中披露的內(nèi)容,這個說明書里也沒有啥新東西。他們 給的規(guī)格說明書的質(zhì)量之低劣達到了荒謬的境地,近乎不可能通過該說明書來使用它們的庫。而且,協(xié)議本身看起來常常也是有意做成具有誤導(dǎo)性的。例如:

  1. 他們使用29字節(jié)的整形數(shù)。
  2. 他們在協(xié)議頭上所有地方都采用低地址存放最高有效字節(jié)(big endian)的格式,除了在某一個字段(而且未標(biāo)明)上采用低地址存放最低有效字節(jié)(little endian)的格式。
  3. 他們在傳輸9K的視頻時,不惜耗費計算能力去壓縮數(shù)據(jù)減少空間,這基本上是沒意義的,因為他們這么折騰一次也就是減少幾位或幾個字節(jié),對這樣的一個文件大小可以忽略不計了。

還有,RTMP是高度以session為導(dǎo)向的,這使得它基本上不可能對流進行組播。理想狀態(tài)下,如果多個用戶要求觀看同一個實時視頻流,我們可以 直接向他們傳回指向單個session的指針,在該session里傳輸這個視頻流(這就是組播的概念)。但是用RTMP的話,我們必須為每一個要求訪問 特定流的用戶創(chuàng)建全新的一個實例。這是完全的浪費。

[[72331]] 

 

我的解決辦法

想到了這些,我決定把典型的響應(yīng)流重新打包和解析為FLV“標(biāo)簽”(這里的“標(biāo)簽”指某個視頻、音頻或者元數(shù)據(jù))。這些FLV標(biāo)簽可以在RTMP下順利地傳輸。

這樣一個方法的好處是:

  • 我們只需要給流重新打包一次(重新打包是一個噩夢,因為缺少規(guī)格說明,還有前面說到的惡心協(xié)議)。
  • 通過套用一個FLV頭,我們可以在客戶端之間順暢地重用任何流,而用內(nèi)部的FLV標(biāo)簽指針(配以某種聲明其在流內(nèi)部確切位置的位移值)就可以訪問到真正的內(nèi)容。

我一開始用我當(dāng)時最熟悉的C語言進行開發(fā)。一段時間后,這個選擇變得麻煩了,所以我開始學(xué)習(xí)Python并移植我的C代碼。開發(fā)過程加快了,但在做 了一些演示版本后,我很快遇到了資源枯竭的問題。Python的socket處理并不適合處理這些類型的情況,具體說,我們發(fā)現(xiàn)在自己的Python代碼 里,每個action都進行了多次系統(tǒng)調(diào)用和context切換,這增加了巨大的系統(tǒng)開銷。

改進性能:混合使用Python和C

在對代碼進行梳理之后,我選擇將性能最關(guān)鍵的函數(shù)移植到內(nèi)部完全用C語言編寫的一個Python模塊中。這基本是底層的東西,具體地說,它利用了內(nèi)核的epoll機制提供了一個O(log n)的算法復(fù)雜度。

在異步socket編程方面,有一些機制可以提供有關(guān)特定socket是否可讀/可寫/出錯之類的信息。過去,開發(fā)人員們可以用select()系 統(tǒng)調(diào)用獲取這些信息,但很難大規(guī)模使用。Poll()是更好的選擇,但它仍然不夠好,因為你每次調(diào)用的時候都要傳遞一大堆socket描述符。

Epoll的神奇之處在于你只需要登記一個socket,系統(tǒng)會記住這個特定的socket并處理所有內(nèi)部的雜亂的細節(jié)。這樣在每次調(diào)用的時候就沒 有傳遞參數(shù)的開銷了。而且它適用的規(guī)模也大有可觀,它只返回你關(guān)心的那些socket,相比用其他技術(shù)時必須從10萬個socket描述符列表里挨個檢查 是否有帶字節(jié)掩碼的事件,其優(yōu)越性真是非同小可啊。

不過,為了性能的提高,我們也付出了代價:這個方法采用了完全和以前不同的設(shè)計模式。該網(wǎng)站以前的方法是(如果我沒記錯的話)單個原始進程,在接收和發(fā)送時會阻塞。我開發(fā)的是一套事件驅(qū)動方案,所以為了適應(yīng)這個新模型,我必須重構(gòu)其他的代碼。

具體地說,在新方法中,我們有一個主循環(huán),它按如下方式處理接收和發(fā)送:

 

 

  1. 接收到的數(shù)據(jù)(作為消息)被傳遞到RTMP層
  2. RTMP包被解析,從中提取出FLV標(biāo)簽
  3. FLV數(shù)據(jù)被傳輸?shù)骄彺婧徒M播層,在該層對流進行組織并填充到底層傳輸緩存中
  4. 發(fā)送程序為每個客戶端保存一個結(jié)構(gòu),包含了最后一次發(fā)送的索引,并盡可能多地向客戶端傳送數(shù)據(jù)

這是一個滾動的數(shù)據(jù)窗口,并包含了某些試探性算法,當(dāng)客戶端速度太慢無法接收時會丟棄一些幀??傮w來說運行的很好。 

系統(tǒng)層級,架構(gòu)和硬件問題

但是我們又遇到另外一個問題:內(nèi)核的context切換成為了一個負擔(dān)。結(jié)果,我們選擇每100毫秒發(fā)送一次而不是實時發(fā)送。這樣可以把小的數(shù)據(jù)包匯總起來,也避免了context切換的爆炸式出現(xiàn)。

也許更大的一個問題在于服務(wù)器架構(gòu)方面:我們需要一個具備負載均衡和容錯能力的服務(wù)器集群,畢竟因為服務(wù)器功能異常而失去用戶不是件好玩的事情。一 開始,我們采用了專職總管服務(wù)器的方法,它指定一個”總管“負責(zé)通過預(yù)測需求來產(chǎn)生和消除播放流。這個方法華麗麗地失敗了。實際上,我們嘗試過的每個方法 都相當(dāng)明顯地失敗了。最后,我們采用了一個相對暴力的方法,在集群的各個節(jié)點之間隨機地共享播放的流,使流量基本平衡了。

這個方法是有效的,但是也有一些不足:雖然一般情況下它處理的很好,我們也碰到了當(dāng)所有網(wǎng)站用戶(或者相當(dāng)大比例的用戶)觀看單個廣播流的時候,性 能會變得非常糟糕。好消息是,除了一次市場宣傳活動(marketing campaign)之外,這種情況再也沒出現(xiàn)過。我們部署了另外一套單獨的集群來處理這種情況,但真實的情況是我們先分析了一番,覺得為了一次市場活動而 犧牲付費用戶的體驗是說不過去的,實際上,這個案例也不是一個真實的事件(雖然說能處理所有想象得到的情況也是很好的)。 

結(jié)論

這里有最后結(jié)果的一些統(tǒng)計數(shù)字:每天在集群里的流量在峰值時是大約10萬用戶(60%負載),平均是5萬。我管理了2個集群(匈牙利和美國),每個 里有大約40臺服務(wù)器共同承擔(dān)這個負載。這些集群的總帶寬大約是50 Gbps,在負載達到峰值時大約使用了10 Gbps。最后,我努力做到了讓每臺服務(wù)器輕松地能提供10 Gbps帶寬,也就等于一臺服務(wù)器可以承受30萬用戶同時觀看視頻流。

已有的FMS集群包含了超過200臺服務(wù)器,我只需要15臺就可以取代他們,而且其中只有10臺在真正提供服務(wù)。這就等于200除以10,等于20 倍的性能提高。大概我在這個項目里最大的收獲就是我不應(yīng)讓自己受阻于學(xué)習(xí)新技能的困難。具體說來,Python、轉(zhuǎn)碼、面向?qū)ο缶幊?,這些都是我在做這個 項目之前缺少專業(yè)經(jīng)驗的概念。

這個信念,以及實現(xiàn)你自己的方案的信心,會給你帶來很大的回報。

【1】后來,當(dāng)我們把新代碼投入生產(chǎn),我們又遇到了硬件問題,因為我們使用老的sr2500 Intel架構(gòu)服務(wù)器,由于它們的PCI總線帶寬太低,不能支持10 Gbit的以太網(wǎng)卡。沒轍,我們只好把它們用在1-4×1 Gbit的以太網(wǎng)池中(把多個網(wǎng)卡的性能匯總為一個虛擬網(wǎng)卡)。最終,我們獲得了一些更新的sr2600 i7 Intel架構(gòu)服務(wù)器,它們通過光纖達到了無性能損耗的10 Gbps帶寬。所有上述匯總的結(jié)果都是基于這樣的硬件條件來計算的。

英文原文:GERGELY KALMAN,編譯:@老碼農(nóng)的自留地

譯文鏈接:http://blog.jobbole.com/39323/

責(zé)任編輯:林師授 來源: 伯樂在線
相關(guān)推薦

2013-08-02 11:23:45

2011-06-21 16:26:19

SEO內(nèi)部優(yōu)化

2024-05-28 07:01:29

2010-08-17 13:23:49

2009-06-29 15:39:53

Servlet和JSPServlet引擎

2015-09-16 10:13:16

游戲性能

2011-09-09 09:50:40

Oracle

2011-06-29 18:21:18

關(guān)鍵詞

2023-10-20 08:12:00

JDK21線程池配置

2009-09-14 15:04:44

2009-07-21 10:44:08

ITIL配置管理經(jīng)驗

2011-08-15 10:27:48

2014-03-13 09:20:38

jQueryAngularJs

2009-08-11 15:46:47

2017-01-20 09:43:12

日志告警挖掘

2012-07-13 14:25:59

2009-11-02 11:11:07

VB.NET OOP設(shè)

2012-06-18 10:59:12

WEB開發(fā)項目

2009-07-11 10:30:17

綜合布線工作體會

2009-08-07 17:38:08

C#無詞尾符號
點贊
收藏

51CTO技術(shù)棧公眾號