日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

一臺服務器并發TCP連接數可以有多少?

如何支持從硬件和操作系統上支持單臺服務器支持上萬并發,支持百萬千萬,甚至上億的并發

著名的C10K并發連接問題是什么?C10M并發問題又是什么?

接下來我們逐一的介紹說明

 

服務器支持的并發

在linux下編程,網絡服務器程序我們都知道每一個TCP連接都要占用一個文件描述符,一旦這個文件描述符使用完了,新的連接到就返回錯誤“Socket/File:Can't open so many files”

也就是,我們需要明白操作系統對可以打開的最大文件數的限制

進程限制

執行命令 ulimit -n 輸出256,說明對于一個進程最多打開256個文件,所以如果采用默認的配置最多也就是200多個并發,那么就要修改ulimit打開文件的限制,在/etc/rc.local文件最后,添加ulimt -SHn 100000,這樣就支持一個進程打開10萬個文件,理論并發是10萬

全局限制

執行命令cat /proc/sys/fs/file-nr輸出9344 0 592026分別為:

已經分配的文件句柄數,已經分配但是還沒有使用的文件句柄,最大文件句柄數

我們可以把這個數值改大些,用 root 權限修改 /etc/sysctl.conf 文件:

  • fs.file-max = 1000000
  • net.ipv4.ip_conntrack_max = 1000000
  • net.ipv4.netfilter.ip_conntrack_max = 1000000

端口范圍限制

端口的范圍0-65535,其中1024以下是系統使用的,從1024-65535是給用戶使用的,由于一個TCP連接都要占用一個端口號,所以我們最多可有60000多個并發,其實這樣理解的朋友應該不在少數,這是一個錯誤的理解

如何標識一個TCP連接

系統用一個4元數組來表示唯一的一個連接{local ip,local port,remote ip,remote port},作為服務器端只使用了bind時的這個端口,也就是說,不同的進程,不同的remote IP 都有不同的端口來對應

Server最大TCP連接數

server通常固定在某個本地端口上監聽,等待client連接請求,即使sever端有很多的IP,本地監聽端口也是獨占的,因此server端tcp的四個元組只有remote ip 和 remote port 是可變的,因此最大的TCP連接為客戶端的IP x 客戶端的port數,最大的TCP連接數約為2^32次方(IP數)x 2^16次方(port數),也就是說server端單擊最大tcp連接數約為2^48次方

結論

單個機器理論TCP并發連接數有這么多,但是實際上并發連接肯定受硬件資源(內存),網絡資源(帶寬)的限制,那么如何計算內存和帶寬呢?

假設一個請求(UDP)大小按照548個字節計算,內存4G,帶寬按照5M獨立帶寬計算,那么理論并發X為:

一個UDP的長度在Internet上大約是548個字節,理論長度65535個字節,我們計算暫時按照548個字節

x * 548 < 內存大小, 并且還得小于帶寬大小

計算的結果:5M帶寬,理論并發在9000左右

在目前大部分計算機的計算能力以及分布式架構來說,并發的最大瓶頸還是帶寬的能力

 

C10K問題,單機支持1萬個并發連接問題

在互聯網web1.0的時代,互聯網大部分使用場景下載一個html頁面,用戶在瀏覽器上查看網頁信息,這個時期不存在C10K的問題

隨著web2.0的時代到來,用戶群體幾何倍數增長,也不再是單純的瀏覽網頁,逐漸的開始進行交互,從簡單的表達提交,到即時通訊和在線實時互動,因為每個用戶都需要和服務器保持TCP連接才能進行數據實時交互,就像騰訊這樣的網站同一個時間的并發TCP連接可能就過億

早期的騰訊QQ采用了UDP的這種原始包交換協議來實現的,繞開了C10K的難題,當然了這個過程肯定是痛苦的,如果當時有epoll技術,他們肯定用TCP,眾所周知,后臺的手機QQ,微信都采用了TCP協議和UDP協議的配合

 

實際上,當時也有異步模式,如select/poll模型,這些技術都有一定的缺點,如select最大不能超過1024,poll沒有限制,但是每次收到的數據都需要遍歷每一個連接查看是哪個連接有數據請求

最初的服務器都是基于進程/線程模型的,新連接一個TCP連接,就需要分配一個1個進程,而進程又是操作系統最昂貴的資源,一臺機器無法創建很多進程,如果是C10K就要創建1萬個進程,那么對于單機操作系統而言是無法承受的(效率低下,甚至完全癱瘓),如果采用分布式系統,維持1億用戶在線需要10萬臺服務器成本巨大

那么如何突破單機性能的局限,這是網絡編程最直接要面臨的問題

C10K

在之前的舊服務器上基于select的程序處理1000個并發吞吐量,在2倍性能的機器上往往是處理不了2000個并發的,大量的操作消耗和當前的連接數N成線性關系,大量的操作和消耗和當前的連接數N成線性關系,會導致單個任務的資源消耗和當前的連接數的關系是0(n),而服務程序同時需要數萬計的socket進行I/0處理,積累下的資源消耗會相對的可觀,這顯然會導致系統吞吐量不能和機器性能匹配

C10K最大的特點是,解決了其性能和連接及機器性能的關系是非線性的

一些沒有太多大并發的實踐經驗的技術同行,所實現的諸如IM及時通信,所謂的理論負載動不動就號稱單機支持上萬,上十萬甚至上百萬的情況,是經不起考驗的

C10K的本質問題

是操作系統的問題,傳統的同步阻塞I/0模式都是一樣的,處理的方式都是requests per second,并發10K和100的區別關鍵在于CPU

創建的進程線程多了,數據拷貝頻繁(緩存I/O,內核將數據拷貝到用戶進程空間,阻塞),進程/線程上下文切換消耗巨大,導致操作系統崩潰,這就是C10K的本質問題

解決C10K問題的關鍵就是:盡可能的減少這些CPU等核心的計算資源消耗,從而榨干單臺服務器的性能,突破C10K的關鍵問題

C10K問題的解決方案

主要思路有2個

思路一:一個是對應每一個連接處理分配一個獨立的進程/線程

思路二:另外一個思路是用同一個進程/線程同時處理若干個連接

思路一的擴展性差,占用資源過多,是最老的一種服務器連接處理的方式,我們暫時忽略,直接說第二種的思路

一個進程/線程處理多個連接(IO多路復用)

IO復用從技術實現上分很多種,接下來依次說明各個方式的實現和優劣:

  • 方式1:傳統思路最簡單的方式,循環挨個處理各個連接,每個連接對應一個socket,當所有的socket都有數據的時候,這種方法是可行的,但是當應用讀取某一個socket的文件數據不ready的時候,整個應用會阻塞在這里等待該文件的句柄,即使別的文件句柄ready,也無法往下處理
      • 直接循環處理多個連接
      • 任一文件句柄的不成功,并不會阻塞整個應用

 

  • 方式2:select方案解決阻塞的問題,思路是如果在讀取文件句柄之前,先查下一下他的狀態,ready了就進行處理,否則就不進行處理,于是有了select方案
      • 有連接請求抵達在檢查處理
      • 句柄上限+重復初始化+逐個排查所有文件的句柄狀態效率不高
  • 方式3:poll主要解決了select的前的2個問題,通過一個follfd數組向內核傳遞需要關注的事件消除文件句柄上限,同時使用不同字段分別標注關注的事件和發生事件,來避免重復初始化
      • 設計新的數據結果提高使用效率
      • 逐個排查所有文件句柄的狀態效率不高
  • 方式4:epoll既然逐個排查所有文件句柄狀態效率不高,如果調用返回的時候只給應用提供發生了狀態變化(很可能數據ready)的文件句柄,進行排查的效率不就高了嗎,epoll采用了這種設計,適用于大規模的應用場景,當文件句柄數目超過10之后,epoll性能就優于select和poll,當文件句柄達到10K的時候,epoll就是另外一個數量級
      • 只返回狀態變化的文件句柄
      • 依賴特定的平臺(Linux)
  • 方式5:由于epoll, kqueue, IOCP每個接口都有自己的特點,程序移植非常困難,于是需要對這些接口進行封裝,以讓它們易于使用和移植,其中libevent庫就是其中之一。跨平臺,封裝底層平臺的調用,提供統一的 API,但底層在不同平臺上自動選擇合適的調用。按照libevent的官方網站,libevent庫提供了以下功能:當一個文件描述符的特定事件(如可讀,可寫或出錯)發生了,或一個定時事件發生了,libevent就會自動執行用戶指定的回調函數,來處理事件。目前,libevent已支持以下接口/dev/poll, kqueue, event ports, select, poll 和 epoll。Libevent的內部事件機制完全是基于所使用的接口的。因此libevent非常容易移植,也使它的擴展性非常容易。目前,libevent已在以下操作系統中編譯通過:Linux,BSD,mac OS X,Solaris和windows。使用libevent庫進行開發非常簡單,也很容易在各種unix平臺上移植。一個簡單的使用libevent庫的程序如下:
網絡高并發

 

C10M問題,單機支持1000萬個并發連接問題

截止目前,40gpbs、32-cores、256G RAM的X86服務器在Newegg網站上的報價是幾千美元,實際上這樣的配置,它完全可以處理1千萬個以上的并發連接

在未來IPV6協議下,每個服務器的潛在連接數據都是百萬級,單個服務器處理數百萬的并發甚至上千萬的并發

不要讓OS內核執行所有的繁重任務,將數據包處理,內存管理,處理器調度等任務從內核轉移到應用程序高效的完成,諸如讓linux這樣的OS只處理控制層,數據層完全交給應用程序來處理

面向數據層的系統可以每秒處理1千萬個數據包,面向控制層的系統,每秒只能處理1百萬個數據包,這雖然是很極端的,但是可擴展性是專業化,為了做好這些事情,不能把性能問題外部給操作系統來解決,而是你自己必須要做

 

回顧一下C10K問題

在之前,開發人員處理C10K的擴展性問題的時候,盡量避免了服務器處理超過1萬的并發連接,改進操作系統內核及事件驅動服務器(用Nginx和Node)和代替了線程服務(Apache)

Apache的問題,在于服務器的性能會隨著連接數增多而變差,,比如Apache持續幾秒的短連接,快速的事物,如果每秒處理1000個事物,只能有約1000個并發連接到服務器,如果事務延長到了10秒,要維持每秒1000個事物則必須打開一個萬個并發連接,這種情況下:盡管不顧DoS攻擊,Apache也會性能陡降,同時大量的下載操作也會是Apache崩潰

OS內核中兩個基本的問題:

1、連接數=線程數/進程數:當一個數據包進來,內核會遍歷所有的進程以決定由那個進程來處理這個數據包

2、連接數=選擇數/輪訓次數(單線程):同樣的擴展性問題,每個包都要走一遭列表上所有的Socket

通過上述針對Apache所表現出的問題,實際上徹底解決并發性能問題的解決方法的根本就是改進OS內核使其在常數時間內查找,使線程切換時間與線程數量無關,使用一個新的可擴展epoll()/IOCompletionPort常數時間去做socket查詢。
因為線程調度并沒有得到擴展,所以服務器大規模對socket使用epoll方法,這樣就導致需要使用異步編程模式,而這些編程模式正是Nginx和Node類型服務器具有的。所以當從Apache遷移到Nginx和Node類型服務器時,即使在一個配置較低的服務器上增加連接數,性能也不會突降。所以在處理C10K連接時,一臺筆記本電腦的速度甚至超過了16核的服務器。這也是前一個10年解決C10K問題的普遍方法。

 

實現C10M意味著什么

  • 1千萬的并發連接數
  • 100萬個連接/秒:每個連接以這個速率持續約10秒(單個請求10秒超時)
  • 10GB/秒的連接:快速連接到互聯網
  • 1千萬個數據包/秒:目前的服務器每秒處理50K數據包
  • 10微妙的延遲:可擴展服務也行可以處理這個規模(但延遲會飆升)
  • 10微妙的抖動:限制最大的延遲
  • 并發10核技術:軟件支持更多核的服務器

 

為什么說實現C10M的挑戰不在硬件而在軟件

硬件不是10M問題的性能瓶頸所在處,真正的問題出在軟件上,尤其是*nux操作系統。理由如下面這幾點:
首先:最初的設計是讓Unix成為一個電話網絡的控制系統,而不是成為一個服務器操作系統。對于控制系統而言,針對的主要目標是用戶和任務,而并沒有針對作為協助功能的數據處理做特別設計,也就是既沒有所謂的快速路徑、慢速路徑,也沒有各種數據服務處理的優先級差別。
其次:傳統的CPU,因為只有一個核,操作系統代碼以多線程或多任務的形式來提升整體性能。而現在,4核、8核、32核、64核和100核,都已經是真實存在的CPU芯片,如何提高多核的性能可擴展性,是一個必須面對的問題。比如讓同一任務分割在多個核心上執行,以避免CPU的空閑浪費,當然,這里面要解決的技術點有任務分割、任務同步和異步等。
再次:核心緩存大小與內存速度是一個關鍵問題。現在,內存已經變得非常的便宜,隨便一臺普通的筆記本電腦,內存至少也就是4G以上,高端服務器的內存上24G那是相當的平常。但是,內存的訪問速度仍然很慢,CPU訪問一次內存需要約60~100納秒,相比很久以前的內存訪問速度,這基本沒有增長多少。對于在一個帶有1GHZ主頻CPU的電腦硬件里,如果要實現10M性能,那么平均每一個包只有100納秒,如果存在兩次CPU訪問內存,那么10M性能就達不到了。核心緩存,也就是CPU L1/L2/LL Cache,雖然訪問速度會快些,但大小仍然不夠,我之前接觸到的高端至強,LLC容量大小貌似也就是12M。

 

解決C10M問題的思路總結

 

網卡問題:通過內核工作效率不高
解決方案:使用自己的驅動程序并管理它們,使適配器遠離操作系統。
CPU問題:使用傳統的內核方法來協調你的應用程序是行不通的。
解決方案:Linux管理前兩個CPU,你的應用程序管理其余的CPU,中斷只發生在你允許的CPU上。
內存問題:內存需要特別關注,以求高效。
解決方案:在系統啟動時就分配大部分內存給你管理的大內存頁。
以Linux為例,解決的思路就是將控制層交給Linux,應用程序管理數據。應用程序與內核之間沒有交互、沒有線程調度、沒有系統調用、沒有中斷,什么都沒有。 然而,你有的是在Linux上運行的代碼,你可以正常調試,這不是某種怪異的硬件系統,需要特定的工程師。你需要定制的硬件在數據層提升性能,但是必須是在你熟悉的編程和開發環境上進行。

 

說了這么多,到底什么是高并發呢?

引言:代碼還沒有開始寫,就要考慮萬一哪一天IM用戶量破百萬,千萬該怎么辦,這個是程序員的基本修養

高并發是互聯網系統架構的一個性能指標之一,它通常是指單位時間內系統能夠同時處理的請求數,簡單的說:QPS(Queries per second)

  • 高并發的基本表現為單位時間內系統能夠同時處理的請求數
  • 高并發的核心是對CPU的資源的有效的壓榨

對于大多數互聯網應用來說,CPU不是該系統的瓶頸,系統的大部分的時間的情況下CPU都是在I/O(硬盤/內存/網絡)的讀/寫操作

 

控制變量法

一個經典的C/S的HTTP請求流程:

Client -1-> 負載均衡LVS,Nginx -2-> 服務應用層(JAVA Python Go)-3-> 數據緩存層(redis Memcached)-4-> 持久層(MySQL MongoDB)-4-> 返回給客戶端

網絡高并發

C/S的HTTP請求流程

1、客戶端經過DNS服務器解析,請求到達負載均衡的集群

2、負載均衡服務會配置規則,請求分攤到服務層,服務層是我們的業務核心層

3、在經過緩存層

4、最后持久化數據

5、返回數據給客戶端

要達到高并發,我們需要負載均衡、服務層、緩存層、持久層都是高可用、高性能的。

并行:兩個事件同一時刻完成

并發:兩個事件在同一時間段內交替發生,從宏觀上看,兩個事件都發生了

分享到:
標簽:并發 網絡
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定