99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀千萬級并發(fā)實現(xiàn)的秘密:內(nèi)核不是解決方案,而是問題所在!
千萬級并發(fā)實現(xiàn)的秘密:內(nèi)核不是解決方案,而是問題所在!
2014-11-27
收藏

千萬級并發(fā)實現(xiàn)的秘密:內(nèi)核不是解決方案,而是問題所在!

既然我們已經(jīng)解決了 C10K并發(fā)連接問題,應(yīng)該如何提高水平支持千萬級并發(fā)連接?你可能會說不可能。不,現(xiàn)在系統(tǒng)已經(jīng)在用你可能不熟悉甚至激進的方式支持千萬級別的并發(fā)連接。

要知道它是如何做到的,我們首先要了解Errata Security的CEO Errata Security,以及他在Shmoocon 2013大會上的無稽之談 C10M Defending The Internet At Scale。

Robert用一種我以前從未聽說的方式來很巧妙地解釋了這個問題。他首先介紹了一點有關(guān)Unix的歷史,Unix的設(shè)計初衷并不是一般的服務(wù)器操作系統(tǒng),而是電話網(wǎng)絡(luò)的控制系統(tǒng)。由于是實際傳送數(shù)據(jù)的電話網(wǎng)絡(luò),所以在控制層和數(shù)據(jù)層之間有明確的界限。問題是我們現(xiàn)在根本不應(yīng)該使用Unix服務(wù)器作為數(shù)據(jù)層的一部分。正如設(shè)計只運行一個應(yīng)用程序的服務(wù)器內(nèi)核,肯定和設(shè)計多用戶的服務(wù)器內(nèi)核是不同的。

也就是他所說的關(guān)鍵要理解內(nèi)核不是解決辦法,內(nèi)核是問題所在。

這意味著:

不要讓內(nèi)核執(zhí)行所有繁重的任務(wù)。將數(shù)據(jù)包處理,內(nèi)存管理,處理器調(diào)度等任務(wù)從內(nèi)核轉(zhuǎn)移到應(yīng)用程序高效地完成。讓Linux只處理控制層,數(shù)據(jù)層完全交給應(yīng)用程序來處理。

最終就是要設(shè)計這樣一個系統(tǒng),該系統(tǒng)可以處理千萬級別的并發(fā)連接,它在200個時鐘周期內(nèi)處理數(shù)據(jù)包,在14萬個時鐘周期內(nèi)處理應(yīng)用程序邏輯。由于一次主存儲器訪問就要花費300個時鐘周期,所以這是最大限度的減少代碼和緩存丟失的關(guān)鍵。

面向數(shù)據(jù)層的系統(tǒng)可以每秒處理1千萬個數(shù)據(jù)包,面向控制層的系統(tǒng),每秒只能處理1百萬個數(shù)據(jù)包。

這似乎很極端,請記住一句老話:可擴展性是專業(yè)化的。為了做好一些事情,你不能把性能問題外包給操作系統(tǒng)來解決,你必須自己做。
現(xiàn)在,讓我們學(xué)習(xí)Robert如何創(chuàng)建一個能夠處理千萬級別并發(fā)連接的系統(tǒng)。

C10K問題最近十年

十年前,工程師處理C10K可擴展性問題時,盡量避免服務(wù)器處理超過1萬個的并發(fā)連接。通過改進操作系統(tǒng)內(nèi)核以及用事件驅(qū)動服務(wù)器(如Nginx和Node)代替線程服務(wù)器(Apache),這個問題已經(jīng)被解決。人們用十年的時間從Apache轉(zhuǎn)移到可擴展服務(wù)器,在近幾年,可擴展服務(wù)器的采用率增長得更快了。

Apache的問題

Apache的問題在于服務(wù)器的性能會隨著連接數(shù)的增多而變差

關(guān)鍵點:性能和可擴展性并不是一回事。當(dāng)人們談?wù)撘?guī)模時,他們往往是在談?wù)撔阅?,但是?guī)模和性能是不同的,比如Apache。

持續(xù)幾秒的短期連接,比如快速事務(wù),如果每秒處理1000個事務(wù),只有約1000個并發(fā)連接到服務(wù)器。

事務(wù)延長到10秒,要維持每秒1000個事務(wù),必須打開1萬個并發(fā)連接。這種情況下:盡管你不顧DoS攻擊,Apache也會性能陡降;同時大量的下載操作也會使Apache崩潰。

如果每秒處理的連接從5千增加到1萬,你會怎么做?比方說,你升級硬件并且提高處理器速度到原來的2倍。發(fā)生了什么?你得到兩倍的性能,但你沒有得到兩倍的處理規(guī)模。每秒處理的連接可能只達到了6000。你繼續(xù)提高速度,情況也沒有改善。甚至16倍的性能時,仍然不能處理1萬個并發(fā)連接。所以說性能和可擴展性是不一樣的。

問題在于Apache會創(chuàng)建一個CGI進程,然后關(guān)閉,這個步驟并沒有擴展。

為什么呢?內(nèi)核使用的O(N^2)算法使服務(wù)器無法處理1萬個并發(fā)連接。

內(nèi)核中的兩個基本問題:

連接數(shù)=線程數(shù)/進程數(shù)。當(dāng)一個數(shù)據(jù)包進來,內(nèi)核會遍歷其所有進程以決定由哪個進程來處理這個數(shù)據(jù)包。

連接數(shù)=選擇數(shù)/輪詢次數(shù)(單線程)。同樣的可擴展性問題,每個包都要走一遭列表上所有的socket。

解決方法:改進內(nèi)核使其在常數(shù)時間內(nèi)查找。

使線程切換時間與線程數(shù)量無關(guān)。

使用一個新的可擴展epoll()/IOCompletionPort常數(shù)時間去做socket查詢。

因為線程調(diào)度并沒有得到擴展,所以服務(wù)器大規(guī)模對socket使用epoll方法,這樣就導(dǎo)致需要使用異步編程模式,而這些編程模式正是Nginx和Node類型服務(wù)器具有的;所以當(dāng)從Apache遷移到Nginx和Node類型服務(wù)器時,即使在一個配置較低的服務(wù)器上增加連接數(shù),性能也不會突降;所以在10K連接時,一臺筆記本電腦的速度甚至超過了16核的服務(wù)器。

C10M問題未來十年

不遠的將來,服務(wù)器將要處理數(shù)百萬的并發(fā)連接。IPv6協(xié)議下,每個服務(wù)器的潛在連接數(shù)都是數(shù)以百萬級的,所以處理規(guī)模需要升級。

如IDS / IPS這類應(yīng)用程序需要支持這種規(guī)模,因為它們連接到一個服務(wù)器骨干網(wǎng)。其他例子:DNS根服務(wù)器,TOR節(jié)點,互聯(lián)網(wǎng)Nmap,視頻流,銀行,Carrier NAT,VoIP PBX,負載均衡器,網(wǎng)頁緩存,防火墻,電子郵件接收,垃圾郵件過濾。

通常人們將互聯(lián)網(wǎng)規(guī)模問題歸根于應(yīng)用程序而不是服務(wù)器,因為他們賣的是硬件+軟件。你買設(shè)備,并將其應(yīng)用到你的數(shù)據(jù)中心。這些設(shè)備可能包含一塊Intel主板或網(wǎng)絡(luò)處理器以及用來加密和檢測數(shù)據(jù)包的專用芯片等。

截至2013年2月,40Gpbs,32芯,256G RAM 的X86處理器在Newegg網(wǎng)站上的報價是5000美元。該服務(wù)器可以處理1萬個以上的并發(fā)連接,如果它們不能,那是因為你選擇了錯誤的軟件,而不是底層硬件的問題。這個硬件可以很容易地擴展到1千萬個并發(fā)連接。

10M的并發(fā)連接挑戰(zhàn)意味著什么:


  1. 1千萬的并發(fā)連接數(shù)
  2. 100萬個連接/秒每個連接以這個速率持續(xù)約10秒
  3. 10GB/秒的連接快速連接到互聯(lián)網(wǎng)。
  4. 1千萬個數(shù)據(jù)包/秒據(jù)估計目前的服務(wù)器每秒處理50K的數(shù)據(jù)包,以后會更多。過去服務(wù)器每秒可以處理100K的中斷,并且每一個數(shù)據(jù)包都產(chǎn)生中斷。
  5. 10微秒的延遲可擴展服務(wù)器也許可以處理這個規(guī)模,但延遲可能會飆升。
  6. 10微秒的抖動限制最大延遲
  7. 并發(fā)10核技術(shù)軟件應(yīng)支持更多核的服務(wù)器。通常情況下,軟件能輕松擴展到四核。服務(wù)器可以擴展到更多核,因此需要重寫軟件,以支持更多核的服務(wù)器。


我們所學(xué)的是Unix而不是網(wǎng)絡(luò)編程

很多程序員通過W. Richard Stevens所著的《Unix網(wǎng)絡(luò)編程》學(xué)習(xí)網(wǎng)絡(luò)編程技術(shù)。問題是,這本書是關(guān)于Unix的,而不只是網(wǎng)絡(luò)編程。它告訴你,讓Unix做所有繁重的工作,你只需要在Unix的上層寫一個小服務(wù)器。但內(nèi)核規(guī)模不夠,解決的辦法是盡可能將業(yè)務(wù)移動到內(nèi)核之外,并且自己處理所有繁重的業(yè)務(wù)。

這方面有影響的一個例子是Apache每個連接線程的模型。這意味著線程調(diào)度程序根據(jù)將要到來的數(shù)據(jù)確定接下來調(diào)用哪一個read()函數(shù),也就是把線程調(diào)度系統(tǒng)當(dāng)作數(shù)據(jù)包調(diào)度系統(tǒng)來用。(我真的很喜歡這一點,從來沒有想過這樣的說法)。

Nginx宣稱,它不把線程調(diào)度當(dāng)作數(shù)據(jù)包調(diào)度程序,而是自己進行數(shù)據(jù)包調(diào)度。使用select找到socket,我們知道數(shù)據(jù)來了,就可以立即讀取并處理數(shù)據(jù),數(shù)據(jù)也不會堵塞。

經(jīng)驗:讓Unix處理網(wǎng)絡(luò)堆棧,但之后的業(yè)務(wù)由你來處理。

怎樣編寫規(guī)模較大的軟件?

如何改變你的軟件,使其規(guī)?;??許多只提升硬件性能去支撐項目擴展的經(jīng)驗都是錯誤的,我們需要知道性能的實際情況。

要達到到更高的水平,需要解決的問題如下:


  1. 數(shù)據(jù)包的可擴展性
  2. 多核的可擴展性
  3. 內(nèi)存的可擴展性


實現(xiàn)數(shù)據(jù)包可擴展編寫自己的個性化驅(qū)動來繞過堆棧

數(shù)據(jù)包的問題是它們需經(jīng)Unix內(nèi)核的處理。網(wǎng)絡(luò)堆棧復(fù)雜緩慢,數(shù)據(jù)包最好直接到達應(yīng)用程序,而非經(jīng)過操作系統(tǒng)處理之后。

做到這一點的方法是編寫自己的驅(qū)動程序。所有驅(qū)動程序?qū)?shù)據(jù)包直接發(fā)送到應(yīng)用程序,而不是通過堆棧。你可以找到這種驅(qū)動程序:PF_RING,NETMAP,Intel DPDK(數(shù)據(jù)層開發(fā)套件)。Intel不是開源的,但有很多相關(guān)的技術(shù)支持。

速度有多快?Intel的基準是在一個相當(dāng)輕量級的服務(wù)器上,每秒處理8000萬個數(shù)據(jù)包(每個數(shù)據(jù)包200個時鐘周期)。這也是通過用戶模式。將數(shù)據(jù)包向上傳遞,使用用戶模式,處理完畢后再返回。Linux每秒處理的數(shù)據(jù)包個數(shù)不超過百萬個,將UDP數(shù)據(jù)包提高到用戶模式,再次出去。客戶驅(qū)動程序和Linux的性能比是80:1。

對于每秒1000萬個數(shù)據(jù)包的目標(biāo),如果200個時鐘周期被用來獲取數(shù)據(jù)包,將留下1400個時鐘周期實現(xiàn)類似DNS / IDS的功能。

通過PF_RING得到的是原始數(shù)據(jù)包,所以你必須做你的TCP堆棧。人們所做的是用戶模式棧。Intel有現(xiàn)成的可擴展TCP堆棧

多核的可擴展性

多核可擴展性不同于多線程可擴展性。我們都熟知這個理念:處理器的速度并沒有變快,我們只是靠增加數(shù)量來達到目的。
大多數(shù)的代碼都未實現(xiàn)4核以上的并行。當(dāng)我們添加更多內(nèi)核時,下降的不僅僅是性能等級,處理速度可能也會變得越來越慢,這是軟件的問題。我們希望軟件的提高速度同內(nèi)核的增加接近線性正相關(guān)。
多線程編程不同于多核編程

多線程

每個CPU內(nèi)核中不止一個線程

用鎖來協(xié)調(diào)線程(通過系統(tǒng)調(diào)用)

每個線程有不同的任務(wù)

多核

每個CPU內(nèi)核中只有一個線程

當(dāng)兩個線程/內(nèi)核訪問同一個數(shù)據(jù)時,不能停下來互相等待

同一個任務(wù)的不同線程

要解決的問題是怎樣將一個應(yīng)用程序分布到多個內(nèi)核中去

Unix中的鎖在內(nèi)核實現(xiàn)。4內(nèi)核使用鎖的情況是大多數(shù)軟件開始等待其他線程解鎖。因此,增加內(nèi)核所獲得的收益遠遠低于等待中的性能損耗。

我們需要這樣一個架構(gòu),它更像高速公路而不是紅綠燈控制的十字路口,無需等待,每個人都以自己的節(jié)奏行進,盡可能節(jié)省開銷。

解決方案:

在每個核心中保存數(shù)據(jù)結(jié)構(gòu),然后聚合的對數(shù)據(jù)進行讀取。

原子性。CPU支持可以通過C語言調(diào)用的指令,保證原子性,避免沖突發(fā)生。開銷很大,所以不要處處使用。

無鎖的數(shù)據(jù)結(jié)構(gòu)。線程無需等待即可訪問,在不同的架構(gòu)下都是復(fù)雜的工作,請不要自己做。

線程模型,即流水線與工作線程模型。這不只是同步的問題,而是你的線程如何架構(gòu)。

處理器關(guān)聯(lián)。告訴操作系統(tǒng)優(yōu)先使用前兩個內(nèi)核,然后設(shè)置線程運行在哪一個內(nèi)核上,你也可以通過中斷到達這個目的。所以,CPU由你來控制而不是Linux。

內(nèi)存的可擴展性

如果你有20G的RAM,假設(shè)每次連接占用2K的內(nèi)存,如果你還有20M的三級緩存,緩存中會沒有數(shù)據(jù)。數(shù)據(jù)轉(zhuǎn)移到主存中處理花費300個時鐘周期,此時CPU沒有做任何事情。

每個數(shù)據(jù)包要有1400個時鐘周期(DNS / IDS的功能)和200個時鐘周期(獲取數(shù)據(jù)包)的開銷,每個數(shù)據(jù)包我們只有4個高速緩存缺失,這是一個問題。

聯(lián)合定位數(shù)據(jù)

不要通過指針在滿內(nèi)存亂放數(shù)據(jù)。每次你跟蹤一個指針,都會是一個高速緩存缺失:[hash pointer] -> [Task Control Block] -> [Socket] -> [App],這是四個高速緩存缺失。

保持所有的數(shù)據(jù)在一個內(nèi)存塊:[TCB |socket| APP]。給所有塊預(yù)分配內(nèi)存,將高速緩存缺失從4減少到1。

分頁

32GB的數(shù)據(jù)需占用64MB的分頁表,不適合都存儲在高速緩存。所以存在兩個高速緩存缺失分頁表和它所指向的數(shù)據(jù)。這是開發(fā)可擴展的軟件不能忽略的細節(jié)。

解決方案:壓縮數(shù)據(jù),使用有很多內(nèi)存訪問的高速緩存架構(gòu),而不是二叉搜索樹

NUMA架構(gòu)加倍了主存訪問時間。內(nèi)存可能不在本地socket,而是另一個socket上。

內(nèi)存池

啟動時立即預(yù)先分配所有的內(nèi)存

在對象,線程和socket的基礎(chǔ)上進行分配。

超線程

每個網(wǎng)絡(luò)處理器最多可以運行4個線程,英特爾只能運行2個。

在適當(dāng)?shù)那闆r下,我們還需要掩蓋延時,比如內(nèi)存訪問中一個線程在等待另一個全速的線程。

大內(nèi)存頁

減小頁表規(guī)模。從一開始就預(yù)留內(nèi)存,讓你的應(yīng)用程序管理內(nèi)存。

總結(jié)

網(wǎng)卡

問題:通過內(nèi)核工作效率不高

解決方案:使用自己的驅(qū)動程序并管理它們,使適配器遠離操作系統(tǒng)。

CPU

問題:使用傳統(tǒng)的內(nèi)核方法來協(xié)調(diào)你的應(yīng)用程序是行不通的。

解決方案:Linux管理前兩個CPU,你的應(yīng)用程序管理其余的CPU。中斷只發(fā)生在你允許的CPU上。

內(nèi)存

問題:內(nèi)存需要特別關(guān)注,以求高效。

解決方案:在系統(tǒng)啟動時就分配大部分內(nèi)存給你管理的大內(nèi)存頁

控制層交給Linux,應(yīng)用程序管理數(shù)據(jù)。應(yīng)用程序與內(nèi)核之間沒有交互,沒有線程調(diào)度,沒有系統(tǒng)調(diào)用,沒有中斷,什么都沒有。
然而,你有的是在Linux上運行的代碼,你可以正常調(diào)試,這不是某種怪異的硬件系統(tǒng),需要特定的工程師。你需要定制的硬件在數(shù)據(jù)層提升性能,但是必須是在你熟悉的編程和開發(fā)環(huán)境上進行。

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗服務(wù)器是否宕機 new_captcha: data.new_captcha, // 用于宕機時表示是新驗證碼的宕機 product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }