原文地址:https://blog.csdn.net/weiwangchao_/article/details/52610272html
在tcp應用中,server事先在某個固定端口監聽,client主動發起鏈接,通過三路握手後創建tcp鏈接。那麼對單機,其最大併發tcp鏈接數是多少?linux
如何標識一個TCP鏈接git
在肯定最大鏈接數以前,先來看看系統如何標識一個tcp鏈接。系統用一個4四元組來惟一標識一個TCP鏈接:{local ip, local port,remote ip,remote port}。github
一,client最大tcp鏈接數編程
client每次發起tcp鏈接請求時,除非綁定端口,一般會讓系統選取一個空閒的本地端口(local port),該端口是獨佔的,不能和其餘tcp鏈接共享。tcp端口的數據類型是unsigned short,所以本地端口個數最大隻有65536,端口0有特殊含義,不能使用,這樣可用端口最多隻有65535,因此在所有做爲client端的狀況下,最大tcp鏈接數爲65535,這些鏈接能夠連到不一樣的server ip。服務器
二,server最大tcp鏈接數網絡
server一般固定在某個本地端口上監聽,等待client的鏈接請求。不考慮地址重用(unix的SO_REUSEADDR選項)的狀況下,即便server端有多個ip,本地監聽端口也是獨佔的,所以server端tcp鏈接4元組中只有remote ip(也就是client ip)和remote port(客戶端port)是可變的,所以最大tcp鏈接爲客戶端ip數×客戶端port數,對IPV4,不考慮ip地址分類等因素,最大tcp鏈接數約爲2的32次方(ip數)×2的16次方(port數),也就是server端單機最大tcp鏈接數約爲2的48次方。併發
三,實際的tcp鏈接數運維
上面給出的是理論上的單機最大鏈接數,在實際環境中,受到機器資源、操做系統等的限制,特別是sever端,其最大併發tcp鏈接數遠不能達到理論上限。在unix/linux下限制鏈接數的主要因素是內存和容許的文件描述符個數(每一個tcp鏈接都要佔用必定內存,每一個socket就是一個文件描述符),另外1024如下的端口一般爲保留端口。在默認2.6內核配置下,通過試驗,每一個socket佔用內存在15~20k之間。socket
影響一個socket佔用內存的參數包括:
rmem_max
wmem_max
tcp_rmem
tcp_wmem
tcp_mem
grep skbuff /proc/slabinfo
對server端,經過增長內存、修改最大文件描述符個數等參數,單機最大併發TCP鏈接數超過10萬 是沒問題的,國外 Urban Airship 公司在產品環境中已作到 50 萬併發 。在實際應用中,對大規模網絡應用,還須要考慮C10K 問題。
原文:
http://wanshi.iteye.com/blog/1256282
http://www.cnblogs.com/Solstice/archive/2011/07/01/2095411.html
http://unix.stackexchange.com/questions/30509/what-is-the-formula-to-determine-how-much-memory-a-socket-consumes-under-linux
http://serverfault.com/questions/10852/what-limits-the-maximum-number-of-connections-on-a-linux-server
http://soft.chinabyte.com/os/285/12349285.shtml
曾幾什麼時候咱們還在尋求網絡編程中C10K問題的解決方案,可是如今從硬件和操做系統支持來看單臺服務器支持上萬併發鏈接已經沒有多少挑戰性了。
咱們先假設單臺服務器最多隻能支持萬級併發鏈接,其實對絕大多數應用來講已經遠遠足夠了,可是對於一些擁有很大用戶基數的互聯網公司,每每面臨的併發鏈接數是百萬,千萬,甚至騰訊的上億(注:QQ默認用的UDP協議)。雖然如今的集羣,分佈式技術能夠爲咱們將併發負載分擔在多臺服務器上,那咱們只須要擴展出數十臺電腦就能夠解決問題,可是咱們更但願能更大的挖掘單臺服務器的資源,先努力垂直擴展,再進行水平擴展,這樣能夠有效的節省服務器相關的開支(硬件資源,機房,運維,電力其實也是一筆不小的開支)。
那麼到底一臺服務器可以支持多少TCP併發鏈接呢?
在linux下編寫網絡服務器程序的朋友確定都知道每個tcp鏈接都要佔一個文件描述符,一旦這個文件描述符使用完了,新的鏈接到來返回給咱們的錯誤是「Socket/File:Can't open so many files」。
這時你須要明白操做系統對能夠打開的最大文件數的限制。
進程限制
執行 ulimit -n 輸出 1024,說明對於一個進程而言最多隻能打開1024個文件,因此你要採用此默認配置最多也就能夠併發上千個TCP鏈接。
臨時修改:ulimit -n 1000000,可是這種臨時修改只對當前登陸用戶目前的使用環境有效,系統重啓或用戶退出後就會失效。
重啓後失效的修改(不過我在CentOS 6.5下測試,重啓後未發現失效):編輯 /etc/security/limits.conf 文件, 修改後內容爲
* soft nofile 1000000
* hard nofile 1000000
永久修改:編輯/etc/rc.local,在其後添加以下內容
ulimit -SHn 1000000
全侷限制
執行 cat /proc/sys/fs/file-nr 輸出 9344 0 592026
,分別爲:1.已經分配的文件句柄數,2.已經分配但沒有使用的文件句柄數,3.最大文件句柄數。但在kernel 2.6版本中第二項的值總爲0,這並非一個錯誤,它實際上意味着已經分配的文件描述符無一浪費的都已經被使用了 。
咱們能夠把這個數值改大些,用 root 權限修改 /etc/sysctl.conf 文件:
fs.file-max = 1000000
net.ipv4.ip_conntrack_max = 1000000
net.ipv4.netfilter.ip_conntrack_max = 1000000
操做系統上端口號1024如下是系統保留的,從1024-65535是用戶使用的。因爲每一個TCP鏈接都要佔一個端口號,因此咱們最多能夠有60000多個併發鏈接。我想有這種錯誤思路朋友不在少數吧?(其中我過去就一直這麼認爲)
咱們來分析一下吧
如何標識一個TCP鏈接:系統用一個4四元組來惟一標識一個TCP鏈接:{local ip, local port,remote ip,remote port}。好吧,咱們拿出《UNIX網絡編程:卷一》第四章中對accept的講解來看看概念性的東西,第二個參數cliaddr表明了客戶端的ip地址和端口號。而咱們做爲服務端實際只使用了bind時這一個端口,說明端口號65535並非併發量的限制。
server最大tcp鏈接數:server一般固定在某個本地端口上監聽,等待client的鏈接請求。不考慮地址重用(unix的SO_REUSEADDR選項)的狀況下,即便server端有多個ip,本地監聽端口也是獨佔的,所以server端tcp鏈接4元組中只有remote ip(也就是client ip)和remote port(客戶端port)是可變的,所以最大tcp鏈接爲客戶端ip數×客戶端port數,對IPV4,不考慮ip地址分類等因素,最大tcp鏈接數約爲2的32次方(ip數)×2的16次方(port數),也就是server端單機最大tcp鏈接數約爲2的48次方。
上面給出的結論都是理論上的單機TCP併發鏈接數,實際上單機併發鏈接數確定要受硬件資源(內存)、網絡資源(帶寬)的限制,至少對咱們的需求如今能夠作到數十萬級的併發了,你的呢?
這種單臺機器10w併發,不考慮內存cpu的實現,主要是程序網絡模型的選擇。項目在Github上有提供https://github.com/yaocoder/HPNetServer