很早以前就聽說了c10k,c100k,c1000k等問題,每個問題的解決都是併發程式設計的乙個里程碑。隨著硬體的快速提公升,那麼10m(千萬)併發連線呢?能否做到?如何做到?會有什麼限制?小編對此很好奇,折騰了不少時間,終於有了令人興奮的答案!
下面我們使用
庫自帶的例子程式,來跑出乙個單機千萬併發連線的例項,先上操作步驟,後面解釋。
10m連線,大家的個人電腦肯定無法滿足要求,如果不是在大公司任職,弄個實際的物理機對大家是個奢望。那麼怎麼辦?我也面臨同樣問題。
現在的雲計算這麼發達,還可以按小時計費,一小時的費用也就幾元,那就試試雲計算產品吧。小編先是在阿里雲上測試,但阿里雲的按需付費主機配置不高,費了不少時間,最終只跑到了3m個連線。阿里雲的不行,是主機的配置問題還是程式的問題呢?為了得到最終的結論,我嘗試了其他的雲產品,最終ucloud的雲主機給了我驚喜。
首先建立ucloud主機
ucloud主機(一共需要兩台,一台作為伺服器,一台作為客戶端):
. 選擇主機管理的建立主機
. 系統選擇ubuntu14.4 64bit (小編的測試程式是c++11,需要高版本的g++)
. 機型標準版
. 網路增強一定要選擇開啟 (千萬連線是網路io密集型,網路當然要強大型)
. cpu 16核 記憶體64g 資料盤0
. 下一步中的網路型別選擇基礎網路即可,建立主機之後,需要購買彈性ip,並且繫結到主機
. **:小編實驗時(2023年8月),上述的配置,一台僅需7.2元一小時,兩台不到15元
做實驗的時候,大家記得要眼疾手快哦,一小時十幾元,獲得了自己想要的結果就趕緊釋放主機哈
10m併發連線對系統是個挑戰,需要調整相關的引數
sysctl -w fs.file-max=10485760 #系統允許的檔案描述符數量10m
sysctl -w net.ipv4.tcp_rmem=1024 #每個tcp連線的讀取緩衝區1k,乙個連線1k
sysctl -w net.ipv4.tcp_wmem=1024 #每個tcp連線的寫入緩衝區1k
#修改預設的本地埠範圍
sysctl -w net.ipv4.ip_local_port_range='1024 65535'
sysctl -w net.ipv4.tcp_tw_recycle=1 #快速**time_wait的連線
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_timestamps=1
#使用者單程序的最大檔案數,使用者登入時生效
echo '* soft nofile 1048576' >> /etc/security/limits.conf
echo '* hard nofile 1048576' >> /etc/security/limits.conf
ulimit -n 1048576 #使用者單程序的最大檔案數 當前會話生效
下面可以開始部署我們的測試程式了
apt-get update
apt-get install -y screen git make g++ nload iptraf
git clone
cd handy
git checkout 97b5426f91d37
make -j4
選取一台主機s作為伺服器,執行伺服器
10m/10m-svr 100 300 10 301 #啟動10個子程序,每個程序分別監聽100-300的埠
選取另一台主機c作為客戶端,執行客戶端,(需要填寫s的內網ip)
#啟動10個客戶端子程序,連線到s的100-300埠,發起10m個連線,在500秒內建立所有的連線,每600秒傳送乙個心跳,心跳資料為64位元組,多程序的管理埠為301
10m/10m-cli 100 300 10000000 500 10 600 64 301
觀察結果
然後,10m連線的建立就不需要更多的步驟啦,使用命令
watch ss -s
我們就可以開始觀察連線的建立進度啦,看著連線漸漸的往上走,超過10k,100k, 1m是不是很有成就感。
併發連線數到達千萬時,有諸多方面的問題需要解決:
. 單程序最大檔案數量限制:limit -n 最多能把這個數字修改到1048575,因此單個程序最多能夠開啟百萬個檔案,千萬併發連線需要千萬個檔案描述符,於是我們使用多程序來做到千萬檔案的支援
.多程序之間的負載均衡:nginx使用多程序來增加自己的吞吐量,原先採用共享鎖的方式來平衡負載,對核數較多的伺服器,較多的程序並沒有達到效能的線性提公升。最新的linux核心引入了so_reuseport選項,該選項可以自動平衡監聽同一埠的多程序,是核心級的解決方案。handy採用該方案,優於nginx的舊有方式(最新的nginx也支援so_reuseport)。
.測試中客戶端本地埠不夠:讓伺服器監聽了200個埠,這樣客戶端連線伺服器的每個埠只有50k個連線,然後加大預設的本地埠範圍就可以滿足要求(見前面的伺服器系統引數)
測試中如果一次性建立千萬個連線,則絕大部分的連線建立都會失敗,因此讓客戶端每100ms建立2000個連線,提高連線建立的成功率。
系統在執行中,並沒有多少的負載,當然啦,一部分負載跑到底層的hypervisor去了
小編實驗的機器上記憶體占用大約40g,平均乙個連線前後一共用了4k,不多不多
大家可以通過iptraf,nload等工具來檢視系統的網路情況
寫到這裡,順便給出我測是的ucloud主機的效能引數吧:
網絡卡流量最多可以到1.2gbit/s,並非所有時間都到了這麼高,並不穩定,一般在800m-1.2g之間波動
tcp收包發包的最高qps是12w/s,多了就上不去了
為了達到千萬條連線,折騰了不少問題,上面只是個大概,有些地方的細節並沒有深入**。如果大家有興趣,後續會慢慢把其他細節分享出來。
--------2017-12-02更新測試結果-------
最近看見阿里推出了網路增強型伺服器,pps能夠達到450w,於是拿handy的千萬連線進行了測試。在阿里雲上面,按量購買無法購買到最高配的虛機,最高的只購買了下面機型:
網路增強型,60w pps,16核,64g
命令如下
handy/10m/10m-svr 100 500 16 501 #伺服器
handy/10m/10m-cli 100 500 10000000 150 16 170 64 501 # 150s建立1千萬連線
能夠完成千萬條連線,達到的pps大約是20w,進一步增加網路負載會導致一定程度丟包,這個qps與主機聲稱的60w差距較大,可能跟當時共享的機器有關
網路增強型,100wpps,8核,32g
命令如下
handy/10m/10m-svr 100 500 16 501 #伺服器
handy/10m/10m-cli 100 500 6500000 30 16 40 64 501 # 30s 建立650w連線
32g記憶體只到650w連線,達到的pps大約是65w,進一步增加網路負載會導致一定程度丟包
handy的各個測試中,應用的效能都會隨著主機的效能提公升而提公升,瓶頸主要是在系統的記憶體和網絡卡io處
Web伺服器 併發伺服器 長連線(3 4 4)
每次new socket都被強制關閉,造成短連線 所提不要關閉套接字 但是不關閉的話,瀏覽器不知道發完沒有啊 此時用到header的屬性content length 將http body的長度裝到返回頭,送出給瀏覽器 當瀏覽器獲取完資料了之後,就不會再載入了 設定非堵塞 tcp sever sock...
Web伺服器 併發伺服器 長連線(3 4 4)
目錄 每次new socket都被強制關閉,造成短連線 所提不要關閉套接字 但是不關閉的話,瀏覽器不知道發完沒有啊 此時用到header的屬性content length 將http body的長度裝到返回頭,送出給瀏覽器 當瀏覽器獲取完資料了之後,就不會再載入了 設定非堵塞 tcp sever s...
linux伺服器調整引數支援高併發
服務端調整系統的引數,在 etc sysctl.conf中 net.core.somaxconn 2048 net.core.rmem default 262144 net.core.wmem default 262144 net.core.rmem max 16777216 net.core.wm...