客户端多线程分组模拟高频并发数据
前言
之前我们学习了多线程的基础知识,接来我们将使用多线程对客户端进行升级
实现客户端多线程分组模拟高频发送数据,来测试服务端的单线程的效率瓶颈
一、客户端升级模型
1、设计概述
使用C++11提供的多线程接口设计客户端程序,创建指定数量的客户端,然后将客户端的任务平均到每个线程中进行执行
2、设计思路
1、创建一个UI线程,其线程执行函数为cmdThread(),用于输入命令退出程序
2、创建一个全局客户端数组client,其中存储客户端对象
3、为了将所有客户端的任务平均,我们设定了一个全局变量tCount,代表要创建多少个客户端数据处理线程
4、在main()中创建tCount数量的线程,每个线程中所操作的客户端数量平均,线程执行函数为sendThread()
二、测试
- 测试环境 -> Windows本地 -> Release86
t -> 代表线程数
c -> 代表客户端连接数
m -> 代表消息大小
x1 -> 代表每次发送消息数量
1、EasyTcpServer_t1_c1024 -> EasyTcpClient_t1_c1000_m100x1
2、EasyTcpServer_t1_c1024 -> EasyTcpClient_t4_c1000_m100x1
3、EasyTcpServer_t1_c1024*4 -> EasyTcpClient_t4_c4000_m100x1
4、测试结论
- 我们可以看到,服务端在单线程,FD_SIZE=1024的情况下
- 客户端使用单线程,1000连接,每个发送100K的消息包,服务端每秒可以处理8万多消息包
- 客户端使用4线程,1000连接,每个发送100K的消息包,服务端每秒可以处理60多万消息包
- 客户端使用4线程,4000连接,每个发送100K的消息包,服务端每秒可以处理40多万消息包
- 客户端使用了多线程的情况下,这样可以通过连接数或者消息包的数量来提高客户端的消息发送频率
- 这样可以帮助测试
服务端性能瓶颈
- 这样可以帮助测试
三、完整代码
这里只修改了client.cpp的代码,其他的代码没有修改(参考“十三、添加高精度计时器测试性能”)
1、client.cpp
#include "EasyTcpClient.hpp"
#include<thread>
bool g_bRun = true;
void cmdThread()
{
while (true)
{
char cmdBuf[256] = {};
scanf("%s", cmdBuf);
if (0 == strcmp(cmdBuf, "exit"))
{
g_bRun = false;
printf("退出cmdThread线程\n");
break;
}
else {
printf("不支持的命令。\n");
}
}
}
//客户端数量
const int cCount = 4000;
//发送线程数量
const int tCount = 4;
//客户端数组
EasyTcpClient* client[cCount];
void sendThread(int id)
{
//4个线程 ID 1~4
int c = cCount / tCount;
int begin = (id - 1) * c;
int end = id * c;
for (int n = begin; n < end; n++)
{
client[n] = new EasyTcpClient();
}
for (int n = begin; n < end; n++)
{
client[n]->Connect("127.0.0.1", 4567);
printf("thread<%d>,Connect=%d\n", id, n);
}
std::chrono::milliseconds t(5000);
std::this_thread::sleep_for(t);
Login login;
strcpy(login.userName, "lyd");
strcpy(login.PassWord, "lydmm");
while (g_bRun)
{
for (int n = begin; n < end; n++)
{
client[n]->SendData(&login);
//client[n]->OnRun();
}
}
for (int n = begin; n < end; n++)
{
client[n]->Close();
}
}
int main()
{
//启动UI线程
std::thread t1(cmdThread);
t1.detach();
//启动发送线程
for (int n = 0; n < tCount; n++)
{
std::thread t1(sendThread, n + 1);
t1.detach();
}
while (g_bRun)
Sleep(100);
printf("已退出。\n");
return 0;
}