Linux LVS高并发测试程序,内核参数设置,连接数查询指令
来源:互联网 发布:unity3d 联机unet 编辑:程序博客网 时间:2024/06/15 16:18
最近在公司参与了一个LVS系统测试的项目,学习到了一些关于高并发测试相关的知识,写到博客里记录下
Linux内核参数设置
在服务器端需要调整系统最大文件句柄数
ulimit -n 1000000
在服务器硬件支持,以及服务较轻量的情况下,最大连接数未必只限于100000,视情况而定吧客户端需要发起大量连接,理论上是最多可支持65535个连接,但实际上Linux的默认可用端口号并没有这么多,需要修改
sudo echo 1024 65534 > /proc/sys/net/ipv4/ip_local_port_range
查看连接个数
我们一开始用的是 netstat -nap | grep 程序名 | grep ESTABLISHED| wc -l
来查询,这个指令当连接数上万后就变得很慢,而且我们发现了一个略坑的问题,通过这组合指令查询到的结果是波动的,我特意试了10000个连接下,在程序没有报有连接关闭的情况下,通过netstat查出来的连接个数在9998到10000之间波动。最后我换了个指令 ss state ESTABLISHED dport = :端口号 and dst IP | wc -l
通过ss指令查询,不仅速度很快,而且不会出现计数不准的情况,需要注意的是,查询到的连接数要比实际多1
测试程序
/*client1.cpp *该程序需要libevent库支持 *测试有无LVS时连接延时区别的程序 *程序发起指定数量的连接后,将每秒给服务器发送一个报文,每个连接收到 *服务器返回的报文后计算耗时 */#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/time.h>#include <iostream>#include <map>#include <vector>#include <string>#include "event2/bufferevent.h"#include "event2/buffer.h"#include "event2/listener.h"#include "event2/util.h"#include "event2/event.h"using namespace std;typedef struct bufferevent* BufferEvent;map<struct bufferevent*, long long> bufferevent_map;map<struct bufferevent*, long long>::iterator iter;static int index_ = 0;struct cb_arg{ struct event *ev; struct timeval tv;};void timeout_cb(int fd, short event, void *params){ if (iter == bufferevent_map.end()) { return ; } char buf[1024]; struct cb_arg *arg = (struct cb_arg*)params; struct event *timeout = arg->ev; struct timeval tv = arg->tv; struct timeval start; struct bufferevent *bufevt = iter->first; gettimeofday(&start,NULL); iter->second = 1000000 * start.tv_sec + start.tv_usec; sprintf(buf, "%lld", iter->second); bufferevent_write(bufevt, buf, strlen(buf)); printf("fd %u send %s\n", fd, buf); index_++; iter++; evtimer_add(timeout, &tv);}void read_cb(struct bufferevent *bufevt, void *arg){ char line[1024] = {0}; size_t n; evutil_socket_t fd = bufferevent_getfd(bufevt); struct timeval start; map<struct bufferevent*, long long>::iterator it_temp; it_temp = bufferevent_map.find(bufevt); if (it_temp == bufferevent_map.end()) { return ; } gettimeofday(&start,NULL); long long now = 1000000 * start.tv_sec + start.tv_usec; long long used = now - it_temp->second; while (n = bufferevent_read(bufevt, line, 1024), n > 0) { printf("fd=%u, used time: %lld us\n", fd, used); }}void error_cb(struct bufferevent *bufevt, short events, void *user_data){ evutil_socket_t fd = bufferevent_getfd(bufevt); if (events & BEV_EVENT_EOF) { printf("Connection closed.\n"); printf("fd %u close !\n", fd); bufferevent_free(bufevt); } else if (events & BEV_EVENT_ERROR) { printf("Got an error on the connection: %s\n", strerror(errno)); printf("fd %u close !\n", fd); bufferevent_free(bufevt); }}int main(int argc, char *argv[]){ if (argc != 4) { printf("参数个数不正确 %d, 需要3个参数,连接个数,IP,端口号\n", argc - 1); return 0; } vector<string> argvs; for (int i = 1; i < argc; ++i) { argvs.push_back(argv[i]); } timeval tv = {1, 0}; int times = atoi(argvs[0].c_str()); int port = atoi(argvs[2].c_str()); struct sockaddr_in sin; struct bufferevent* bufevt; event_base *evbase = event_base_new(); if (evbase == NULL) { printf("err in new event_base\n"); return 0; } struct event* timeout; struct cb_arg arg; timeout = evtimer_new(evbase, timeout_cb, &arg); if (timeout == NULL) { printf("err in new evtimer\n"); return 0; } arg.ev = timeout; arg.tv = tv; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(argvs[1].c_str()); sin.sin_port = htons(port); memset(sin.sin_zero, 0x00, 8); for (int i = 0; i < times; ++i) { int fd = socket(AF_INET, SOCK_STREAM, 0); evutil_make_socket_nonblocking(fd); bufevt = bufferevent_socket_new(evbase, fd, BEV_OPT_CLOSE_ON_FREE); if (bufevt == NULL) { printf("err in new bufferevent, fd %u connect failed !\n", fd); continue ; } bufferevent_setcb(bufevt, read_cb, NULL, error_cb, NULL); bufferevent_enable(bufevt, EV_READ | EV_WRITE | EV_PERSIST); if (bufferevent_socket_connect(bufevt, (struct sockaddr *)&sin, sizeof(sin)) < 0) { printf("err in connect with server, fd %u connect failed !\n", fd); bufferevent_free(bufevt); continue ; } bufferevent_map.insert(make_pair(bufevt, 0)); } iter = bufferevent_map.begin(); evtimer_add(timeout, &tv); event_base_dispatch(evbase); evtimer_del(timeout); event_base_free(evbase); return 0;}
/*server.cpp *该程序需要libevent库支持 *简单的回射服务器 */#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <assert.h>#include <event2/event.h>#include <event2/bufferevent.h>#define LISTEN_BACKLOG 1024static int time_out_count = 0;static int err_conn_count = 0;static int err_accept_count = 0;void do_accept(evutil_socket_t listener, short event, void *arg);void read_cb(struct bufferevent *bev, void *arg);void error_cb(struct bufferevent *bev, short event, void *arg);void write_cb(struct bufferevent *bev, void *arg);int main(int argc, char *argv[]){ if (argc != 2) { printf("参数个数不正确 %d\n", argc); return 0; } int port = atoi(argv[1]); evutil_socket_t listener; listener = socket(AF_INET, SOCK_STREAM, 0); assert(listener > 0); evutil_make_listen_socket_reuseable(listener); struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; sin.sin_port = htons(port); if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); return 1; } if (listen(listener, LISTEN_BACKLOG) < 0) { perror("listen"); return 1; } printf ("Listening...\n"); evutil_make_socket_nonblocking(listener); struct event_base *base = event_base_new(); assert(base != NULL); struct event *listen_event; listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept, (void*)base); event_add(listen_event, NULL); event_base_dispatch(base); printf("The End."); return 0;}void do_accept(evutil_socket_t listener, short event, void *arg){ struct event_base *base = (struct event_base *)arg; evutil_socket_t fd; struct sockaddr_in sin; socklen_t slen; fd = accept(listener, (struct sockaddr *)&sin, &slen); evutil_make_socket_nonblocking(fd); if (fd < 0) { printf("err in accept, err ccode %d, 发生accept错误的个数 %d", errno, ++err_accept_count); return; } printf("ACCEPT: fd = %u\n", fd); struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, error_cb, arg); bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);}void read_cb(struct bufferevent *bev, void *arg){#define MAX_LINE 256 char line[MAX_LINE+1]; int n; evutil_socket_t fd = bufferevent_getfd(bev); while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) { line[n] = '\0'; bufferevent_write(bev, line, n); printf("recv : %s\n", line); }}void write_cb(struct bufferevent *bev, void *arg) {}void error_cb(struct bufferevent *bev, short event, void *arg){ evutil_socket_t fd = bufferevent_getfd(bev); printf("fd = %u, ", fd); if (event & BEV_EVENT_TIMEOUT) { time_out_count++; printf("Timed out, 发生超时连接个数 %d", time_out_count); printf(", err code %d\n", errno); } else if (event & BEV_EVENT_EOF) { printf("connection closed\n"); } else if (event & BEV_EVENT_ERROR) { err_conn_count++; printf("some other error, 连接被异常关闭个数 %d", err_conn_count); printf(", err code %d\n", errno); } bufferevent_free(bev);}
/*client2.cpp *该程序需要libevent库支持 *测试高并发量的测试客户端程序,该程序每隔10s就会通过所有连接向服务 *器发送一个报文,以免长时间没有交互,连接被LVS断掉,同时测试服务器 *的负载 */#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/time.h>#include <iostream>#include <map>#include <vector>#include <string>#include "event2/bufferevent.h"#include "event2/buffer.h"#include "event2/listener.h"#include "event2/util.h"#include "event2/event.h"using namespace std;typedef struct bufferevent* BufferEvent;map<struct bufferevent*, long long> bufferevent_map;map<struct bufferevent*, long long>::iterator iter;FILE* fp = NULL;static int index_ = 0;static int counter = 0;static int begin_time = 0;struct cb_arg{ struct event *ev; struct timeval tv;};void timeout_cb(int fd, short event, void *params){ char buf[1024]; struct cb_arg *arg = (struct cb_arg*)params; struct event *timeout = arg->ev; struct timeval tv = arg->tv; for (iter = bufferevent_map.begin(); iter != bufferevent_map.end(); ++iter) { memset(buf, 0, sizeof(buf)); struct bufferevent *bufevt = iter->first; sprintf(buf, "%lld", iter->second); bufferevent_write(bufevt, buf, strlen(buf)); } evtimer_add(timeout, &tv);}void read_cb(struct bufferevent *bufevt, void *arg){ char line[1024] = {0}; size_t n; evutil_socket_t fd = bufferevent_getfd(bufevt); struct timeval start; map<struct bufferevent*, long long>::iterator it_temp; it_temp = bufferevent_map.find(bufevt); if (it_temp == bufferevent_map.end()) { return ; } while (n = bufferevent_read(bufevt, line, 1024), n > 0) { ; }}void write_count(int count){ char buf[1024] = {0}; int now_time = (int)time(NULL); sprintf(buf, "pass %d s, now connect count %d\n", now_time - begin_time, count); fputs(buf, fp);}void error_cb(struct bufferevent *bufevt, short events, void *user_data){ evutil_socket_t fd = bufferevent_getfd(bufevt); if (events & BEV_EVENT_EOF) { counter--; printf("Connection closed.\n"); printf("fd %u close ! count %d\n", fd , counter); printf("now EST connect count %d\n", counter); bufferevent_free(bufevt); bufferevent_map.erase(bufevt); write_count(counter); } else if (events & BEV_EVENT_ERROR) { counter--; printf("Got an error on the connection: %d\n", errno); printf("fd %u close ! count %d\n", fd , counter); printf("now EST connect count %d\n", counter); bufferevent_free(bufevt); bufferevent_map.erase(bufevt); write_count(counter); }}void create_file(){ char buf[1024] = {0}; timeval tv; gettimeofday(&tv, NULL); int time_ = (int) (1000000 * tv.tv_sec + tv.tv_usec); sprintf(buf, "result_%d.txt", time_); fp = fopen(buf, "w+"); if (fp == NULL) { printf("create result file failed!\n"); exit(-1); }}int main(int argc, char *argv[]){ if (argc != 4) { printf("参数个数不正确 %d, 需要3个参数,连接个数,IP,端口号\n", argc - 1); return 0; } vector<string> argvs; for (int i = 1; i < argc; ++i) { argvs.push_back(argv[i]); } create_file(); timeval tv = {10, 0}; int times = atoi(argvs[0].c_str()); int port = atoi(argvs[2].c_str()); struct sockaddr_in sin; struct bufferevent* bufevt; event_base *evbase = event_base_new(); if (evbase == NULL) { printf("err %d in new event_base\n", errno); return 0; } struct event* timeout; struct cb_arg arg; timeout = evtimer_new(evbase, timeout_cb, &arg); if (timeout == NULL) { printf("err in new evtimer\n"); return 0; } arg.ev = timeout; arg.tv = tv; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(argvs[1].c_str()); sin.sin_port = htons(port); memset(sin.sin_zero, 0x00, 8); for (int i = 0; i < times; ++i) { int fd = socket(AF_INET, SOCK_STREAM, 0); evutil_make_socket_nonblocking(fd); bufevt = bufferevent_socket_new(evbase, fd, BEV_OPT_CLOSE_ON_FREE); if (bufevt == NULL) { printf("err %d in new bufferevent, fd %u connect failed !\n", fd, errno); continue ; } bufferevent_setcb(bufevt, read_cb, NULL, error_cb, NULL); bufferevent_enable(bufevt, EV_READ | EV_WRITE | EV_PERSIST); if (bufferevent_socket_connect(bufevt, (struct sockaddr *)&sin, sizeof(sin)) < 0) { printf("err %d in connect with server, fd %u connect failed !\n", fd, errno); continue ; } char buf[64] = {0}; sprintf(buf, "%d", i); bufferevent_map.insert(make_pair(bufevt, 0)); bufferevent_write(bufevt, buf, strlen(buf)); usleep(10); counter++; } printf("now EST connect count %d\n", counter); write_count(counter); evtimer_add(timeout, &tv); event_base_dispatch(evbase); evtimer_del(timeout); event_base_free(evbase); return 0;}
0 0
- Linux LVS高并发测试程序,内核参数设置,连接数查询指令
- Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数
- Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数
- SOCKET -linux下高测试并发socket连接数限制详解
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux下高并发socket最大连接数
- Linux配置支持高并发TCP连接(socket最大连接数)
- Linux配置支持高并发TCP连接(socket最大连接数)
- CODEFORCES #339 div2 A
- Java IO流类继承关系及使用说明
- akka基础 : 理解Actor 系统
- Qt Creator添加/查找槽错误
- 机器学习开篇
- Linux LVS高并发测试程序,内核参数设置,连接数查询指令
- 计算机书籍的一点总结
- Java多线程编程
- 重写equals和hashcode
- 后端服务(综合)
- 自定义视图与工厂模式
- Good Bye 2015
- 大数据(四) - MapReduce
- Java笔记14:泛型初探