最近在公司参与了一个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