Linux服務端最大并發(fā)數(shù)是多少?
1. 開場白
在開始今天的文章之前,先拋一個面試題出來:
你接觸過的單機最大并發(fā)數(shù)是多少?
你認為當前正常配置的服務器物理機最大并發(fā)數(shù)可以到多少?
說說你的理解和分析。
思考幾分鐘,如果你可以有理有據(jù)地說出答案,那確實就不用再往下看了,關上手機去陪陪家人是個不錯的選擇。
思考幾分鐘,如果你沒有頭緒或者對答案不確定,那么你先不用著急關閉頁面去玩耍,你應該繼續(xù)往下看,因為這個問題很不錯。
對于后端開發(fā)人員來說,并發(fā)數(shù)往往和技術難度是呈正相關的,實際上也確實如此:體量決定架構。
服務端根據(jù)不同業(yè)務場景會有不同的側重點,單純追求高并發(fā)其實并不是根本目的,高可用&穩(wěn)定性更重要。
所以最終我們的目的是:保證高可用高穩(wěn)定的基礎上追求高并發(fā),降本增效。
高可用&高并發(fā)是我們直觀感受到的,本質(zhì)上這是個復雜的系統(tǒng)工程,每個環(huán)節(jié)都會影響結果,每一塊都值得研究和深入。
2. C10K問題和C10M問題
在2000年初的時候,全球互聯(lián)網(wǎng)的規(guī)模并不大,但是當時就已經(jīng)提出了C10K問題,所謂C10K就是單機1w并發(fā)問題,雖然現(xiàn)在不覺得是個難題了,但是這在當初是很有遠見和挑戰(zhàn)的問題。
C10K問題最早由Dan Kegel發(fā)布于其個人站點,原文鏈接如下:
http://www.kegel.com/c10k.html
相關資料顯示Dan Kegel目前工作于Google,從1978年起開始接觸計算機編程,是Winetricks和Crosstool的作者,大佬年輕時的照片:
Dan Kegel這篇文章閱讀難度并不大,大白建議從事服務端開發(fā)或者對高性能網(wǎng)絡開發(fā)有興趣的讀者嘗試讀一讀。
在APUE第三版都沒有提到epoll,所以我們解決C10K問題的時間并不長,其中IO復用epoll/kqueue/iocp等技術對于C10k問題的解決起到了非常重要的作用。
開源大神們基于epoll/kqueue等開發(fā)了諸如libevent/libuv等網(wǎng)絡庫,從而大幅提高了高并發(fā)網(wǎng)絡的開發(fā)效率,對于C/C++程序員來說并不陌生。
這里簡單提一下針對下一個10年的展望和挑戰(zhàn):C10M問題。
站在浪尖的那一批人早就開始思考讓單機達到1000w并發(fā),現(xiàn)在聽起來感覺不可思議,但是要達到這個目標,除了硬件上的提升,更重要的是對系統(tǒng)軟件和協(xié)議棧的改造。
Errata Security的CEO Robert Graham在Shmoocon 2013大會上的演講,大佬重要的觀點是:
不要讓OS內(nèi)核執(zhí)行所有繁重的任務:將數(shù)據(jù)包處理、內(nèi)存管理、處理器調(diào)度等任務從內(nèi)核轉移到應用程序高效地完成,讓諸如Linux這樣的OS只處理控制層,數(shù)據(jù)層完全交給應用程序來處理。
確實也是如此,難道你不覺得Linux內(nèi)核做了太多不該自己做的事情了嗎?
近幾年出現(xiàn)的DPDK、PFRING、NETMAP等技術也是類似的思想,現(xiàn)在流行的協(xié)處理器+CPU的架構也是這樣的:
3. 服務器最大并發(fā)數(shù)分析
前面提到的C10K和C10M問題都是圍繞著提升服務器并發(fā)能力展開的,但是難免要問:服務器最大的并發(fā)上限是多少?
3.1 五元組
做過通信的盆友們一定聽過五元組這個概念,一個五元組可以唯一標記一個網(wǎng)絡連接,所以要理解和分析最大并發(fā)數(shù),就必須理解五元組:
這樣的話,就可以基本認為:理論最大并發(fā)數(shù) = 服務端唯一五元組數(shù)。
3.2 端口&IP組合數(shù)
那么對于服務器來說,服務端唯一五元組數(shù)最大是多少呢?
有人說是65535,顯然不是,但是之所以會有這類答案是因為當前Linux的端口號是2字節(jié)大小的short類型,總計2^16個端口,除去一些系統(tǒng)占用的端口,可用端口確實只剩下64000多了。
對于服務端本身來說,DestPort數(shù)量確實有限,假定有多張網(wǎng)卡,每個網(wǎng)卡綁定多個IP,服務端的Port端口數(shù)和IP數(shù)的組合類型也是有限的。
對于客戶端來說,本身的端口和IP也是一樣有限的,雖然這是個組合問題,但是數(shù)量還是有限的:
3.3 并發(fā)數(shù)理論極限
看了前面的端口&IP的組合數(shù)計算,好像并發(fā)數(shù)并不會特別大。
錯了,是真的會很大。
分析一下,前面的計算都是針對單個服務器或者客戶端的,但是實際上每個服務器會應對全網(wǎng)的所有客戶端,那么從服務端看,源IP和源Port的數(shù)量是非常大的。
理論上服務端可以接受的客戶端IP是2^32(按照IPv4計算),端口數(shù)是2^16,目前端口號仍然是16bit的,所有這個理論最大值是2^48,果然很大!
3.4 實際情況
天下沒有免費的午餐。
每一條連接都是要消耗系統(tǒng)資源的,所以實際中可能會設置最大并發(fā)數(shù)來保證服務器的安全和穩(wěn)定,所以這個理論最大并發(fā)數(shù)是不可能達到的。
實際中并發(fā)數(shù)和業(yè)務是直接相關的,像Redis這種內(nèi)存型的服務端并發(fā)十幾萬都是沒問題的,大部分來講幾十/幾百/幾千/幾萬等是存在的。
4. 客戶端最大連接數(shù)
理解了服務器的最大并發(fā)數(shù)是2^48,那么客戶端最多可以連接多少服務器呢?
對于客戶端來說,當然可以借助于多網(wǎng)卡多IP來增加連接能力,我們?nèi)匀患俣蛻舳酥挥?張網(wǎng)卡1個IP,由于端口數(shù)的限制到2^16,再去掉系統(tǒng)占用的端口,剩下可用的差不多64000。
也就是說,客戶端雖然可以連接任意的目的IP和目的端口,但是客戶端自身端口是有限的,所以客戶端的理論最大連接數(shù)是2^16,含系統(tǒng)占用端口。
5. NAT環(huán)境下的客戶端
解決前面的兩個問題之后,來看另外一個問題:
一個公網(wǎng)出口NAT服務設備最多可同時支持多少內(nèi)網(wǎng)IP并發(fā)訪問外網(wǎng)服務?
畢竟公網(wǎng)IP都是有限并且要花錢的,我們大部分機器都是在局域網(wǎng)中結合NAT來進行外網(wǎng)訪問的,所以這個場景還是很熟悉的。
來看下內(nèi)網(wǎng)機器訪問外網(wǎng)時的IP&端口替換和映射還原的過程,就明白了:
因為這時的客戶端是NAT設備,所以NAT環(huán)境下最多支持65535個并發(fā)訪問外網(wǎng)。
6.小結
本文通過一道面試題切入,先描述了C10K和C10M問題,進而詳細說明了客戶端的最大訪問數(shù)和服務端的最大并發(fā)數(shù)計算和原理,最后描述了NAT場景下的訪問并發(fā)數(shù)。
雖然理論服務端并發(fā)數(shù)非常大,但是我們也沒有必要覺得并發(fā)數(shù)高就厲害,服務復雜程度不一樣,切忌唯并發(fā)數(shù)來判斷業(yè)務和開發(fā)者水平。
試想echo服務和訂單交易服務顯然是不一樣的,我們應該做的是在服務穩(wěn)定和高可用的前提下去從緩存/網(wǎng)絡/數(shù)據(jù)庫等多個角度來優(yōu)化提高性能。