日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

100万并发连接服务器笔记之测试端就绪

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 100万并发连接服务器笔记之测试端就绪 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

重新編寫測試端程序

測試端程序需要增加綁定本機IP和本地端口的功能,以盡可能的向外發出更多的tcp請求。需要對client1.c重構,增加參數傳遞。 下面是client2.c的代碼

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108#include <sys/types.h>#include <sys/time.h>#include <sys/queue.h>#include <stdlib.h>#include <err.h>#include <event.h>#include <evhttp.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <sys/socket.h>#include <netinet/in.h>#include <time.h>#include <pthread.h>#define BUFSIZE 4096#define SLEEP_MS 10char buf[BUFSIZE];int bytes_recvd = 0;int chunks_recvd = 0;int closed = 0;int connected = 0;static char ip_array[300] = "192.168.190.134,192.168.190.143,192.168.190.144,192.168.190.145,192.168.190.146,192.168.190.147,192.168.190.148,192.168.190.149,192.168.190.151,192.168.190.152";static char server_ip[16] = "192.168.190.133";static int server_port = 8000;static int max_conns = 62000;// called per chunk receivedvoid chunkcb(struct evhttp_request *req, void *arg) { int s = evbuffer_remove( req->input_buffer, &buf, BUFSIZE ); bytes_recvd += s; chunks_recvd++; if (connected >= max_conns && chunks_recvd % 10000 == 0) printf(">Chunks: %d\tBytes: %d\tClosed: %d\n", chunks_recvd, bytes_recvd, closed);}// gets called when request completesvoid reqcb(struct evhttp_request *req, void *arg) { closed++;}int main(int argc, char **argv) { int ch; while ((ch = getopt(argc, argv, "o:h:p:m:")) != -1) { switch (ch) { case 'h': printf("host is %s\n", optarg); strncpy(server_ip, optarg, 15); break; case 'p': printf("port is %s\n", optarg); server_port = atoi(optarg); /*strncpy(server_ip, optarg, 15);*/ break; case 'm': printf("max_conns is %s\n", optarg); max_conns = atoi(optarg); /*strncpy(server_ip, optarg, 15);*/ break; case 'o': printf("ori_ips is %s\n", optarg); strncpy(ip_array, optarg, 300 - 1); break; } } event_init(); struct evhttp *evhttp_connection; struct evhttp_request *evhttp_request; char path[32]; int i; char delims[] = ","; char *ori_ip = NULL; ori_ip = strtok( ip_array, delims ); while (ori_ip != NULL) { for (i = 1; i <= max_conns; i++) { evhttp_connection = evhttp_connection_new(server_ip, server_port); evhttp_connection_set_local_address(evhttp_connection, ori_ip); evhttp_set_timeout(evhttp_connection, 864000); // 10 day timeout evhttp_request = evhttp_request_new(reqcb, NULL); evhttp_request->chunk_cb = chunkcb; sprintf(&path, "/test/%d", ++connected); if (i % 1000 == 0) printf("Req: %s\t->\t%s\n", ori_ip, &path); evhttp_make_request( evhttp_connection, evhttp_request, EVHTTP_REQ_GET, path ); evhttp_connection_set_timeout(evhttp_request->evcon, 864000); event_loop( EVLOOP_NONBLOCK ); if ( connected % 1000 == 0 ) printf("\nChunks: %d\tBytes: %d\tClosed: %d\n", chunks_recvd, bytes_recvd, closed); usleep(SLEEP_MS * 10); } ori_ip = strtok( NULL, delims ); } event_dispatch(); return 0;}
view rawclient2.c?hosted with ? by?GitHub

若不指定端口,系統會隨機挑選沒有使用到的端口,可以節省些心力。

編譯:

gcc -o client2 client2.c -levent

參數解釋

  • -h 要連接的服務器IP地址
  • -p 要連接的服務器端口
  • -m 本機IP地址需要綁定的隨機端口數量
  • -o 本機所有可用的IP地址列表,注意所有IP地址都應該可用

運行:

./client2 -h 192.168.190.230 -p 8000 -m 64000 -o 192.168.190.134,192.168.190.143,192.168.190.144,192.168.190.145,192.168.190.146,192.168.190.147,192.168.190.148,192.168.190.149,192.168.190.150,192.168.190.151

太長了,每次執行都要粘貼過去,直接放在一個client2.sh文件中,執行就很簡單方便多了。

#!/bin/sh ./client2 -h 192.168.190.230 -p 8000 -m 64000 -o 192.168.190.134,192.168.190.143,192.168.190.144,192.168.190.145,192.168.190.146,192.168.190.147,192.168.190.148,192.168.190.149,192.168.190.150,192.168.190.151

保存,賦值可運行:

chmod +x client2.sh

啟動測試:

sh client2.sh

第三個遇到的問題:fs.file-max的問題

測試端程序client2.c在發出的數量大于某個值(大概為40萬時)是,通過dmesg命令查看會得到大量警告信息:

[warn] socket: Too many open files in system

此時,就需要檢查/proc/sys/fs/file-max參數了。

查看一下系統對fs.file-max的說明

/proc/sys/fs/file-max This file defines a system-wide limit on the number of open files for all processes. (See also setrlimit(2), which can be used by a process to set the per-process limit, RLIMIT_NOFILE, on the number of files it may open.) If you get lots of error messages about running out of file handles, try increasing this value: echo 100000 > /proc/sys/fs/file-max The kernel constant NR_OPEN imposes an upper limit on the value that may be placed in file-max. If you increase /proc/sys/fs/file-max, be sure to increase /proc/sys/fs/inode-max to 3-4 times the new value of /proc/sys/fs/file-max, or you will run out of inodes.

file-max表示系統所有進程最多允許同時打開所有的文件句柄數,系統級硬限制。Linux系統在啟動時根據系統硬件資源狀況計算出來的最佳的最大同時打開文件數限制,如果沒有特殊需要,不用修改,除非打開的文件句柄數超過此值。

在為測試機分配4G內存時,對應的fs.file-max值為386562,很顯然打開的文件句柄很受限,38萬個左右。 很顯然,無論是測試端還是服務端,都應該將此值調大些,一定要大于等于/etc/security/limits.conf送所設置的soft nofile和soft nofile值。?
注意ulimit -n,僅僅設置當前shell以及由它啟動的進程的資源限制。

備注:以上參數,具有包含和被包含的關系。

當前會話修改,可以這么做:

echo 1048576 > /proc/sys/fs/file-max

但系統重啟后消失。

永久修改,要添加到 /etc/sysctl.conf 文件中:

fs.file-max = 1048576

保存并使之生效:

sysctl -p

再測,就不會出現此問題了。

一臺6G內存機器測試機,分配7個網卡,可以做到不占用虛擬內存,對外發出64000 * 7 = 448000個對外持久請求。要完成100萬的持久連接,還得再想辦法。

最終測試端組成如下:

  • 兩臺物理機器各自一個網卡,每個發出64000個請求
  • 兩個6G左右的centos測試端機器(綁定7個橋接或NAT連接)各自發出64000*7 = 448000請求
  • 共使用了16個網卡(物理網卡+虛擬網卡)
  • 1M ≈ 1024K ≈ 1024000 = (64000) + (64000) + (64000*7) + (64000*7)
  • 共耗費16G內存,16個網卡(物理+虛擬),四臺測試機

備注:?
下面就要完成1M持久連接的目標,但在服務端還會遇到最后一個問題。

總結

以上是生活随笔為你收集整理的100万并发连接服务器笔记之测试端就绪的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。