[EVE] CarbonIO與BlueNet:下一代的網路技術

看板ONLINE (線上遊戲)作者 (人,原來不是人)時間13年前 (2012/05/15 15:00), 編輯推噓0(002)
留言2則, 2人參與, 最新討論串1/1
原始英文連結:http://community.eveonline.com/devblog.asp?a=blog&nbid=2332 簡體文章連結:http://eve.tiancity.com/homepage/article/2012/05/15/35308.html 這是中國CCP翻譯歐服Devblog的成果,底下已轉成繁體 我有在twitter上建議Horace先翻一些跟TiDi有關的Devblog文章,這雖然不是我建議的那 幾篇,但依舊很好看,這種充滿技術名詞的文件光看頭就大了,幸好中國CCP會持續翻譯 到全部翻完,即使仍舊看不太懂,但有中文可看真是太棒了!! ============================================================================== 【開發日誌】CarbonIO與BlueNet:下一代的網絡技術 作者:CCP Curt 譯者:CCP Lion 大多數熟悉EVE的人都知道,它是用Python語言編寫的,如果要說得更具體點,那就是 Stackless Python。Stackless是在Python基礎上編寫的一套微線程框架,它能在不產生 大量Python自身額外開銷的情況下同時容納數百萬條的線程。但話還是要說回來,它畢竟 還是Python,因此擺脫不了“解釋器全局鎖”(Global Interpreter Lock,下文將其簡 稱為GIL)。 GIL是一個序列鎖,用來保證在任何時候都只能有一個線程利用Python解釋器(包括其 所有數據)來運行自己。因此,儘管Stackless Python感覺上好像具備多線程處理能力, 但實際上它還是單線程的,只不過運用了任務分離、頻道、定時器及共享內存等一系列招 數而已。 其實過去有些協作式的多任務操作系統也是這樣幹的,其好處是保證了所有線 程都能被執行,不會出現被操作系統提前結束這一情況(除非被操作系統懷疑非法宕機) 。 GIL的存在使得程序員在編寫遊戲邏輯時能自信推斷出程序的全局狀態,省去了一大 堆採用異步回調函數的麻煩。 但這樣有一大缺點:由於EVE中有部分框架的代碼是用Python編寫的,因此它們都免不了 GIL造成的負面影響。 比如,一段用來讀取Python數據的C++語言代碼必須在獲得GIL後才 能讀取一個字符串。 圖片短網址:http://tinyurl.com/77s5fcc http://image.tiancity.com/article/UserFiles/Image/EVE/2012/05/15/eve0515 _a01.jpg 使用Python的任務都要獲得GIL才能合法地被處理,這樣等同於Python任務都是 單線程執行。 (這圖畫得不太好看,人家只是個程序員,不是美術師哦) 一言以蔽之,Stackless Python 代碼的運行速度不會高於你最快的那個CPU核心的速度。 在一台4核或8核CPU的服務器上,其中只有一核在超負荷運作,其他都沒派上用場。當然 ,為了讓這些CPU核心物盡其用,我們可以在它們身上加載更多的節點。對於EVE中許多無 狀態或對共享狀態依賴度極低的代碼而言,這沒什麼問題。但對於像太空模擬或空間站行 走這樣高度依賴共享狀態的代碼而言,就成了一個大問題。 假設一個CPU核心就能處理所有的邏輯並且寫出來的Python代碼較為清晰,那我之前說的 都不是什麼問題。不過,想必我不用說大家也知道,儘管Gridlock等小組已經在優化工作 方面做到了其極致,但我們現在面臨的情況依舊是單個CPU已經無法處理一場大型會戰了 。最近上市的CPU速度是更快、緩存容量也更大、總線也更寬裕並且具備更好的執行流水 線,但在EVE需要其給力的地方,卻沒有任何進步。近期(也可能包括中長期)的趨勢是 “橫向增長”,即同時運行多個CPU核心。 總體而言,多核CPU的流行對EVE的長遠發展是一大利好。 未來那些30乃至60核CPU的機器 能夠很好地體現EVE集群部署方式的優勢,這是因為CPU核心之間切換的效率將遠遠大於線 程之間切換的效率。但就目前而言,為了提升遊戲運行速度,我們需要把網絡及通用讀寫 這樣的EVE模塊從GIL中解放出來。 多核心、超標量的硬件對當今的網絡遊戲來說,都是個好消息。這些遊戲很適合這種架構 ,並且能很容易地進行並行處理。可惜對於依賴Python的EVE來說,這就算不得好消息了 。那些對運行速度要求極高、不需要Python便利開發優勢的EVE系統需要儘早擺脫GIL的束 縛。CarbonIO在這個方向上可以說是向前邁進了一大步。 CarbonIO 是在StacklessIO 基礎上的一個自然提升。它實際上是個從頭寫起的全新引 擎,目標非常明確:讓網絡流量擺脫GIL的束縛,並且讓任何C++代碼也能這樣做。後半個 目的是重頭戲,我們花了大半年才把它完成。 這裡不得不先稍微提一下StacklessIO。對Stackless Python的網絡通信而言,它可以說 是個質的飛躍。通過讓網絡操作變得具有“無堆棧的意識”,StacklessIO可以將一個被 鎖住的操作轉移到一個未被GIL鎖住的線程上,這樣該操作就可以繼續等候,而Stackless 則繼續處理其他事務。然後,該操作重新獲得GIL,告訴Stackless其操作已完成。這樣, 接收端就可以同步進行,使得通訊速度可以達到操作系統級別,並且能基本上在第一時間 內回報給Python。 圖片短網址:http://tinyurl.com/8xy2lj3 http://image.tiancity.com/article/UserFiles/Image/EVE/2012/05/15/eve0515 _a02.jpg StacklessIO在沒有GIL的情況下完成Python請求 CarbonIO在此基礎上更上一層樓。由於它是在完全脫離於GIL的情況下運行多線程通信 引擎,因此Python與該系統之間的交互便是完全獨立了。沒有Python的要求,它也能收發 數據。 請允許我再強調一下:CarbonIO能在Python不作任何要求的情況下收發數據。這是並發性 的,不需要GIL。 當一個連接通過CarbonIO被建立後,系統會調用WSARecv()開始接收數據。與Python進程 並行的線程池將這些數據解密、解壓縮然後轉義到數據包裡。這些數據包會排隊,等著 Python來處理。 當Python覺得它需要一個數據包時,它會往下調用“可能已將此包準備就緒”的CarbonIO 。這意味著數據在離開隊列被返回整個過程中根本沒有用到GIL。這是一個瞬時過程,至 少也有納秒那麼快。這個並行讀取能力是CarbonIO的第一大好處。 第二大好處便是發送了。數據以其原始形式排在工作線程隊列裡,然後便等著Python來調 用了。 其間的壓縮、加密、打包及WSASend()調用都沒有觸及GIL而發生在另一個線程裡 ,這樣操作系統便可以安排它運行在另一顆CPU上了。C++代碼也可以調用一個方法來這樣 做,並不需要特別的架構變更。StacklessIO也可以那樣做,但在脫離上述背景的情況下 ,這會變得很沒意義。 讓我們再來回顧一下之前提到的“已將此包準備就緒”。但如果我們要安置一個C++回調 鉤子函數,使得非Python模塊能在不觸及Machonet的情況下獲得那個數據,這可行嗎? 行啊,這時我們要用的就是BlueNet了。 CarbonIO不停地進行數據接收,並且能在無Python介入的情況下告訴C++模塊數據已收 到。 Machonet是一個大型功能集合,它負責對會話進行分流、導向及管理,負責對數據包的 時間計劃/發送以及其他一系列將EVE撮合成一個有機整體的功能。由於它是個Python模塊 ,因此所有的數據遲早都必須觸及那倒霉的GIL,無論數據在哪個節點。無論一個C++模塊 的速度有多快,GIL仍然是個繞不過的瓶頸。這使得我們曾經都不太願意做大量的C++優化 ,因為任何優化後取得的優勢都會被Machonet 中的GIL吞噬。 但現在情況不一樣了。 現在C++的系統能通過BlueNet收發數據包,無需再理會GIL。這原來是專門為了空間站行 走設計的。空間站行走功能需要發送大量的表示移動的數據。EVE中太空飛行的那部分功 能所需要收發的數據,我們以前可以用旁門左道的方法來解決,但對於如此近距離的人物 動作,就不行了。 之前我們做的預測顯示,即使把空間站行走發送數據的頻率控制在一 般程度,該功能也會把整個服務器集群拖垮。通過在沒有GIL干擾的情況下對流入/流出 C++原生系統(比如物理系統)的數據進行分流,BlueNet成功地解決了該問題。由於在這 種情況下,數據還是保持著其原生態,因此整個系統運行的速度就比之前提高了。 這個具體是怎麼運作的呢? BlueNet保存著一份所有必要Machonet結構的只讀拷貝,另外 ,所有的數據包前都會附上很小的一段((8到10個字節)數據頭。這個數據頭里含有路徑 信息。當BlueNet接到一個數據包時,它會對其進行檢測,然後合理地再分發:要么轉發到 另一個節點上,要么交給被本地的已註冊的C++應用程序。如果它轉發,那這個過程中將用 不到GIL,根本不會調用Machonet/Python。這意味著我們的代理服務器完全能以並行方式 對BlueNet的數據包進行分流,而不必去經過Python導致額外開銷的產生。那這效率究竟提 高了多少呢? 我們還無法確定,但在降低機器負載及延遲方面,它還是非常非常明顯的。 實際上我們還不能將數據公開,因為它們好得難以置信。 除此之外,CarbonIO也包含了大量底層優化,絕大多數都是小規模的速度提升,但把這些 統統疊加起來,整個系統的運行速度也就有了顯著提高。以下幾點值得一提: 工作分組 雖然我很難在本文中把這事兒說得太細,但CarbonIO非常出色地將工作分組來處理。簡而 言之,就是某些操作有了一個固定的開銷。網絡引擎有許多這樣的開銷,但其他所有具有 重要意義的代碼也有大量開銷。通過一些別出心裁的技巧,我們是可以將許多這樣的工作 合併在一起,這樣就只產生一次開銷。就像把邏輯數據包都組合在一起發送在一個 TCP/IP MTU裡一樣(EVE一直就是這樣幹的),CarbonIO將這一做法進一步深化。一個比 較簡單的例子就是GIL獲取集合。 第一個要嘗試取得GIL的線程會先建立起一個隊列,這樣其他要獲取GIL的線程只需將自己 的喚醒調用排在隊列末尾然後返迴線程池就行。那GIL最後被取得時,第一個線程會吸乾 整個隊列,不必在每次IO喚醒時釋放/重拾GIL。在一個繁忙的服務器上這種情況很多,因 此這種改進對我們來說是一大利好。 openSSL整合 CarbonIO用openSSL來實現SSL,並且能在不鎖定GIL的情況下與該協議數據通信。該庫 只是用作一個BIO對而已,所有的數據導航還是由CarbonIO通過完成端口進行的。這有助 於我們循序漸進地讓EVE變得更安全,甚至將來可以把官方網站上的某些帳號管理功能挪 到EVE客戶端上去,這樣可以更方便大家。 壓縮整合 CarbonIO能利用zlib或snappy對每一個數據包都進行壓縮/解壓縮,這一過程同樣是無 需GIL的。 實戰檢驗 通過對一個繁忙的代理服務器(人數峰值大約1600人,一個平常工作日)的24小時數據的 收集,我們發現CPU的總體使用率與單個用戶的CPU使用率都出現了大幅下降。這都歸功於 CarbonIO的總體架構,其作用就是降低事務的開銷。當服務器變得繁忙之後,這些優化的 效果會被逐漸增多且必須處理的事務所抵消,但在最高負載時,CarbonIO還是讓我們的遊 戲增速了不少。 圖片短網址:http://tinyurl.com/775fsg8 http://image.tiancity.com/article/UserFiles/Image/EVE/2012/05/15/eve0515 _a04.jpg 圖片短網址:http://tinyurl.com/8x7q7eo http://image.tiancity.com/article/UserFiles/Image/EVE/2012/05/15/eve0515 _a05.jpg 以上為24小時內單個用戶的CPU使用率 圖片短網址:http://tinyurl.com/7cd22zw http://image.tiancity.com/article/UserFiles/Image/EVE/2012/05/15/eve0515 _a06.jpg 以上為同樣的24小時內總體CPU使用率 至於SOL(星系)節點,由於它們的主要職責是遊戲機製而非網絡管理,因此它們從該優 化中獲得的優勢並不那麼明顯,但我們還是看到它們的CPU使用率下降了8%-10%。 需要指出的是,在上述的檢驗中我們沒有運用BlueNet,沒有用CarbonIO的數據導航,也 沒有用離GIL的數據壓縮/解壓縮。 總結 總的來說,比起以前,EVE能更好地利用現代服務器硬件帶來的優勢,能讓它在同樣的時 間內完成更多的工作,這樣就間接提升了一個系統所能進行的操作上限。通過將我們的代 碼盡量與GIL脫離,我們反而為那些真正需要用它的代碼騰出了空間。另外,由於不再有 那麼多代碼需要競相獲取GIL,系統的總體運行效率也會提升。有了BlueNet再加上很好的 代碼優化,提速空間已被打開。雖然最後的結果仍有待實踐檢驗,但至少,我們已經消除 了一大瓶頸。 原文 http://community.eveonline.com/devblog.asp?a=blog&nbid=2332 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.130.245.45 art1:轉錄至看板 C_Chat 05/15 15:02 art1:轉錄至看板 GameDesign 05/15 15:23

05/16 10:30, , 1F
這放在online似乎...
05/16 10:30, 1F

05/16 20:35, , 2F
對不起我看不懂...
05/16 20:35, 2F
文章代碼(AID): #1FiVxyb- (ONLINE)
文章代碼(AID): #1FiVxyb- (ONLINE)