100萬并發連接服務器筆記之準備篇
前言
測試一個非常簡單服務器如何達到100萬(1M=1024K連接)的并發連接,并且這些連接一旦連接上服務器,就不會斷開,一直連著。
環境受限,沒有服務器,剛開始都是在自己的DELL筆記本上測試,憑借16G內存,和優秀的vmware workstation虛擬機配合,另外還得外借別人虛擬機使用,最終還得搭上兩臺2G內存的臺式機(安裝centos),最終才完成1M并發連接任務。
- 測試程序也很簡陋,一個C語言所寫服務器程序,沒有任何業務存在,收到請求后發送一些頭部,不斷開連接
- 測試端程序也是使用C語言所寫,發送請求,然后等待接收數據,僅此而已
- 服務器端/測試端內存都受限(8G不夠使用),要想完成1024K的目標,需要放棄一些東西,諸如業務不是那么完整
- 一臺分配10G內存Centos服務器,兩臺分配6G內存Centos測試端,兩臺2G內存Centos測試端
- 假如熱心的您可以提供豐富的服務器資源,那就再好不過了。
- 理論上200萬的并發連接(IO密集型),加上業務,40G-50G的內存大概能夠保證
說明
以前也做過類似的工作,量不大,沒記錄下來,一些壓力測試和調優,隨著時間流逝,早已忘記。這次是從零開始,基本上所有過程都會記錄,一步一步,每一步都會遇到問題,并且給出相關解決問題的方法,最終完成目標。
為了方便,服務器端程序和客戶端測試程序,都是使用C語言,不用像JAVA一樣需要預先指定內存,感覺麻煩。使用較為原始的語言來寫,可以避免不必要的調優工作。這中間,可能會穿插Java代碼的思考方式。
可能需要懂點Linux,C,Java,假如您有更好的做法,或者建議,請直接告知,謝謝。
Linux系統
測試端和服務器端都選用較為熟悉的64位Centos 6.4,32位系統最多支持4G內存,太受限。IO密集型應用,對CPU要求不是很高。另外服務器確保安裝上gcc,那就可以開工了。
所有端系統一旦安裝完之后,默認不做任何設置。
服務器端程序
服務器端程序依賴libev框架,需要提前編譯,然后存放到相應位置。下面是具體服務器端代碼:
編譯
gcc server.c -o server ../include/libev.a -lm
運行
./server -p 8000
在源碼中默認指定了8000端口,可以通過-p進行指定新的端口。 開啟了8000端口進行監聽請求,http協議處理類似于htmlfile chunked塊編碼傳輸。
測試服務器端程序
測試程序使用libevent框架,因其使用簡單,提供豐富易用接口,但需要提前下載,手動安裝:
wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
tar xvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure --prefix=/usr
make
make install
注意make和make install需要root用戶。
測試端程序
client1.c 源碼:
備注:這部分代碼參考了A Million-user Comet Application with Mochiweb, Part 3 ,根據需要有所修改。
編譯
gcc -o client1 client1.c -levent
運行
./client1
可能在64位系統會遇到找不到libevent-2.0.so.5情況,需要建立一個軟連接
ln -s /usr/lib/libevent-2.0.so.5 /lib64/libevent-2.0.so.5
即可自動連接IP地址為192.168.190.133:8000的服務器端應用。
第一個遇到的問題:文件句柄受限
測試端程序輸出
看看測試端程序client1輸出的錯誤信息:
Chunks: 798 Bytes: 402990 Closed: 0
Req: 192.168.190.133 -/test/900
Req: 192.168.190.133 -/test/1000
Chunks: 998 Bytes: 503990 Closed: 0
[warn] socket: Too many open files
[warn] socket: Too many open files
[warn] socket: Too many open files
服務器端程序輸出
服務器端最后一條日志為
online user 1018
兩邊都遇到了文件句柄打開的情況。
在服務器端查看已經連接,并且端口號為8000的所有連接數量:
netstat -nat|grep -i "8000"|wc -l
1019
但與服務器端輸出數量對不上,增加所有已經建立連接的選項:
netstat -nat|grep -i "8000"|grep ESTABLISHED|wc -l
1018
那么剩下的一條數據到底是什么呢?
netstat -nat|grep -i "8000"|grep -v ESTABLISHED
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN
也就是server.c監聽的端口,數量上對的上。
在測試服務器端,查看測試進程打開的文件句柄數量
lsof -n|grep client1|wc -l
1032
再次執行
ulimit -n
1024
也是就是client1應用程序共打開了1032個文件句柄,而不是1024,為什么?
把當前進程所有打開的文件句柄保存到文件中,慢慢研究
lsof -n|grep client1 > testconnfinfo.txt
導出的文件可以參考:
除了第一行,我特意添加上供友善閱讀的頭部列定義,也就是1032行信息,但是需要注意頭部:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
client1 3088 yongboy cwd DIR 253,0 4096 800747 /home/yongboy/workspace/c_socket.io_server/test
client1 3088 yongboy rtd DIR 253,0 4096 2 /test_conn
client1 3088 yongboy txt REG 253,0 9697 799991 /home/yongboy/workspace/c_socket.io_server/test/test_conn_1
client1 3088 yongboy mem REG 253,0 156872 50404 /lib64/ld-2.12.so
client1 3088 yongboy mem REG 253,0 1922152 78887 /lib64/libc-2.12.so
client1 3088 yongboy mem REG 253,0 145720 76555 /lib64/libpthread-2.12.so
client1 3088 yongboy mem REG 253,0 47064 69491 /lib64/librt-2.12.so
client1 3088 yongboy mem REG 253,0 968730 26292 /usr/lib/libevent-2.0.so.5.1.9
client1 3088 yongboy 0u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 1u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 2u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 3u REG 0,9 0 4032 anon_inode
client1 3088 yongboy 4u unix 0xffff88007c82f3c0 0t0 79883 socket
client1 3088 yongboy 5u unix 0xffff880037c34380 0t0 79884 socket
client1 3088 yongboy 6u IPv4 79885 0t0 TCP 192.168.190.134:58693->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 7u IPv4 79889 0t0 TCP 192.168.190.134:58694->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 8u IPv4 79891 0t0 TCP 192.168.190.134:58695->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 9u IPv4 79893 0t0 TCP 192.168.190.134:58696->192.168.190.133:irdmi (ESTABLISHED)
可以看到文件句柄是從0u開始,0u上面的8個(5個mem + 3個啟動)進程,1032 - 8 = 1024個文件句柄,這樣就和系統限制的值吻合了。
root用戶編輯/etc/security/limits.conf文件添加:
* soft nofile 1048576
* hard nofile 1048576
- soft是一個警告值,而hard則是一個真正意義的閥值,超過就會報錯。
- soft 指的是當前系統生效的設置值。hard 表明系統中所能設定的最大值
- nofile - 打開文件的最大數目
- 星號表示針對所有用戶,若僅針對某個用戶登錄ID,請替換星號
注意:
1024K x 1024 = 1048576K = 1M,1百萬多一點。
備注:測試端和服務器端都需要作此設置,保存退出,然后reboot即可生效。
第一個問題,就這樣克服了。再次運行 /client1測試程序,就不會出現受打開文件句柄的限制。但大概在測試端打開對外28200個端口時,會出現程序異常,直接退出。
段錯誤
這個也是程序沒有處理端口不夠用的異常,但可以通過增加端口進行解決。
備注: 但測試端單機最多只能打開6萬多個連接,是一個問題,如何克服,下一篇解決此問題,并且還會遇到文件句柄的受限問題。
posted on 2013-04-09 09:50 nieyong 閱讀(17122) 評論(3) 編輯 收藏 所屬分類: C1M