百萬長連接並發的限制因素


百萬長連接並發的限制因素
(1) CPU:使用top,然后按1查看,如果有邏輯CPU跑到100%,那就是受限了。多線程或線程綁定CPU都可以;
(2) 內存:本文主要討論內存限制;

1. 一個TCP連接默認占內存大小

針對長連接來講,監聽和connect的過程是幾乎不消耗內存的。內存主要消耗在滑動窗口的讀寫緩存上。
使用附錄中的代碼,可以看到默認一個TCP連接占用的內存大小有多大:

[root@localhost test]# ./gtop 
recv_buf = 85k
send_buf = 16k

可以看到一個TCP連接,默認占用的內存大小=85k+16k=101KB,那么我們可以計算了32GB內存,按照內存使用率70%來算,應該能支持的
穩定長連接數=32GB*70%/101KB=232,555≈23萬
PS:因為connect並不耗內存,而內存有可能是會被共享的,所以最初的讀寫並不是每個TCP連接一下就分配了101KB的內存,而是最終會分配這么多。socket讀寫越頻繁越大,內存降的越快。

2. 如何調整

如果根據自己的業務,我們可以調整這個緩沖區大小。
比如,我們的場景是簡歷長連接保持會話,每個報文1KB左右,1min發一次,顯然用不到這么大的發送和接收緩沖區。
可以從程序中設置:(建議從程序中設置)

//c++代碼
int nRecvBuf=16*1024; 
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)); 
int nSendBuf=32*1024;
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));

或者在系統參數中設置:/etc/sysctl.conf(比較不建議這樣設置)

#/etc/sysctl.conf
net.ipv4.tcp_rmem = 4096        87380   2063281
net.ipv4.tcp_wmem = 4096        16384   2063281
net.core.wmem_default = 388608
net.core.rmem_default = 388608
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608

真正起作用的是87380、16384兩個參數所在的位置。設置之后用sysctl -p同步

[root@localhost test]# sysctl -p

同步之后,可以用剛才那個gtop再取一下參數看是否生效了。

附錄一:報錯信息

未調內存之前壓力測試30萬的時候,發現內存一點點減少,但是使用ps和top等工具並沒有查看到任何耗費內存比較多的進程或線程。
當系統內存低於600MB時,系統宕機(並非真的死機,ssh連不上,usb串口連不上),報錯如下

Centos Linux ( )	
Kernel 3 ,10.0-514.e17.64 an 	
loadtest3 login :[ 16221.310569]Out of memory :Kill process 1183 ( tuned)score or sacrif ice child 	
[ 16221.3406031Killed process 1183 ( tuned)total-vm :562728kB,anon-rss :0kB ,file-rss :0kB ,shmem-rss :0kB 	
[ 16221.357102]of memory :Kill process 926 ( )score or sacrif ice child 	
[ 16221.357130]Killed process 926 ( polkitd)total-vm :538128kB ,anon-rss :0kB ,file-rss :0kB ,shmem-rss :	
[ 16221.3599841of memory :Kill process 932 ( gmain)score or sacrifice child 	
[ 16221.360826]Killed process 932 ( gmain)total-vm :538428kB ,anon-rss :0kB ,file-rss :0kB ,shmem-rss :	
[ 16221.3627391of memory :Kill process 33234 ( dstat)score 0 or sacrifice child 	
[ 16221.362766]Killed process 33234 ( dstat)total-vm :150232kB ,anon-rss :0kB ,file-rss :0kB,shmem-rss 	
[ 16230,318655]Out of memory :process 937 ( NetworkMlanagerscore or sacrif ice child 	
6230.310689 ]Killed process 937 ( NetworkManager)total- :,anon-rss :0kB ,file-rss :,shm 	
6230.311222 ]Out of memory :Kill process 948 ( gdbus)score or sacrifice child 	
16230.311222	
16238.3112501K	
Killed process ( gdbus)total-um :450644kB ,anon-rss :,file-rss :4kB ,shmem-rss :0kB 	
16448.675291	
75291 ]INFO :task /::31 blocked for more than 120 seconds 	
[16448.675316]	
53161 echo > /proc/sys/kernel/hung_task_timeout_secs"disables this messag 	
16448.675401	
[16448.675426	
401 ]INFO :task fsnotify mark :189 blocked for more than seconds 	
than seconds 	
16448.675494	
"echo> /proc/sys/kernel/hungtask_timeoutsecs "disables this message 	
[16448.675518	
4 ]INFO :task kworker /:1 :209 blocked for more than 120 seconds 	
16448.675588	
] "echo0 > /proc/sys/kernel/hung_task_timeout_secs"disables this message 	
16448.675611	
INFO :task gdbus :948 blocked for more than seconds 	
[16448.675789]	
echo 0 > /proc/sys/kernel/hung_task_timeout_secs"disables this message 	
[16448.675734]	
INFO :task kworker /:2 :blocked for more than seconds 	
[16568.679395	
echo > /proc/sys/kerne/hung task timeout secs "disables this messag 	
[16568.679424	
INFO :task kworker /4:0 :blocked for more than 120 seconds 	
[16568.679522	
echo > /proc/sys/kernel/hungtask_timeout_secs"disables this messa 	
16568.679553]	
INFO :task fsnotify mark :189 blocked for more than 120 seconds 	
16568.679639	
echo > /proc/sys/kernel/hungtasktimeout _secs"disables this message 	
[16568.679669	
INFO :task kworker /u96:1 :209 blocked for more than seconds 	
[16568.679760	
echo > /proc/sys//hungtask "disables this message 	
[16568.679788	
INFO :task gdbus :948 blocked for more than 120 seconds 	
[16568.6798931	
echo 0 > /proc/sys/kernel/hungtask_timeout_secs"disables this message 	
[16568.679923	
INFO :task kworker /4:2 :16027 blocked for more than 120 seconds 	
] "echo0 > /proc/sys/kernel/hung_task_timeout_secs"disables this message 

附錄二:查詢收發滑動窗口大小的代碼(前文用到的gtop)

編譯命令:g++ main.cpp -o gtop

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <string>
 
#define MAXLINE  4096 
#define OPEN_MAX  16 
#define SERV_PORT  1555 

const int EPOLL_MAX_FDSIZE = 0x4000;

 
int main()
{
    int i , maxi ,listenfd , connfd , sockfd ,epfd, nfds;
    int n;
    char buf[MAXLINE];
    struct epoll_event ev, events[EPOLL_MAX_FDSIZE];  
    socklen_t clilen;
    struct pollfd client[OPEN_MAX];
 
    struct sockaddr_in cliaddr , servaddr;
    listenfd = socket(AF_INET , SOCK_STREAM , 0);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	
    int opt_rc_val;
    socklen_t opt_rc_len = sizeof(opt_rc_val);
    int opt_sd_val;
    socklen_t opt_sd_len = sizeof(opt_sd_val);
	
    getsockopt(listenfd,SOL_SOCKET,SO_RCVBUF,&opt_rc_val, &opt_rc_len); 
    getsockopt(listenfd,SOL_SOCKET,SO_SNDBUF,&opt_sd_val, &opt_sd_len);
    
    printf("recv_buf = %dk\n", opt_rc_val / 1024);
    printf("send_buf = %dk\n", opt_sd_val / 1024);
	
    return 0;
}

附錄三:參考網址

http://www.net-add.com/devops/sre/cdn/28.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM