跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++

仿 Mudou 库 one thread per loop 式并发服务器实现:边缘测试与性能测试

综述由AI生成基于 C++ 实现仿 Mudou 库的 one thread per loop 并发服务器模型,重点进行了边缘场景测试与性能评估。测试涵盖长连接连续请求、超时连接释放(包括数据不完整及业务处理超时场景)、多请求粘包处理、大文件 PUT 上传等边界情况。针对业务处理耗时过长导致其他连接被拖累的问题,提出了将连接释放操作延迟至任务池执行的优化方案。最后使用 Webbench 工具在云服务器环境下进行压力测试,验证了服务器的并发处理能力与 QPS 指标,强调了测试环境对性能评估的重要性。

imJackJia发布于 2026/3/16更新于 2026/5/113 浏览
仿 Mudou 库 one thread per loop 式并发服务器实现:边缘测试与性能测试

服务器边缘测试与性能测试

1. 长连接连续请求测试

长连接测试 1:创建一个客户端持续给服务器发送数据,直到超过超时时间看看是否正常。

#include "httpserver.hpp"
#define WWWROOT "./wwwroot"
std::string RequestStr(const HttpRequest &req) {
    std::stringstream ss;
    ss << req._method << " " << req._path << " " << req._version << "\r\n";
    for(auto&it : req._params){
        ss << it.first << ": " << it.second << "\r\n";
    }
    for(auto&it : req._headers){
        ss << it.first << ": " << it.second << "\r\n";
    }
    ss << "\r\n";
    ss << req._body;
    return ss.str();
}
void Hello(const HttpRequest &req, HttpResponse *rsp){
    rsp->SetContent(RequestStr(req), "text/plain");
    //sleep(15);
}
void Login(const HttpRequest &req, HttpResponse *rsp){
    rsp->SetContent(RequestStr(req), "text/plain");
}
void PutFile(const HttpRequest &req, HttpResponse *rsp){
    std::string path = WWWROOT + req._path;
    Until::WriteFile(path, req._body);
    //rsp->SetContent(RequestStr(req), "text/plain");
}
void DelFile(const HttpRequest &req, HttpResponse *rsp){
    rsp->SetContent(RequestStr(req), "text/plain");
}
int main(){
    HttpServer server(8080);
    server.SetThreadCount(3);
    server.SetBaseDir(WWWROOT);
    server.Get("/hello", Hello);
    server.Post("/login", Login);
    server.Put("/1234.txt", PutFile);
    server.Delete("/1234.txt", DelFile);
    server.Start();
    return 0;
}

2. 超时连接释放测试 1

超时连接测试 1:创建一个客户端,给服务器发送一次数据后,不动了,查看服务器是否会正常的超时关闭连接。

#include "../source/server.hpp"
int main(){
    Socket cli_sock;
    cli_sock.CreateClient(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    while(1){
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        char buf[1024]={0};
        assert(cli_sock.Recv(buf,1023));
        LOG_DEBUG("[%s]", buf);
        sleep(15);
    }
    cli_sock.Close();
    return 0;
}

3. 超时连接释放测试 2

给服务器发送一个数据,告诉服务器要发送 1024 字节的数据,但是实际发送的数据不足 1024,查看服务器处理结果。

  1. 如果数据只发送一次,服务器将得不到完整请求,就不会进行业务处理,客户端也就得不到响应,最终超时关闭连接。
  2. 连着给服务器发送了多次小的请求,服务器会将后边的请求当作前边请求的正文进行处理,而后面处理的时候有可能就会因为处理错误而关闭连接。
#include "../source/server.hpp"
int main(){
    Socket cli_sock;
    cli_sock.CreateClient(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 100\r\n\r\nbitejiuyeke";
    while(1){
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        char buf[1024]={0};
        assert(cli_sock.Recv(buf,1023));
        LOG_DEBUG("[%s]", buf);
        sleep(3);
    }
    cli_sock.Close();
    return 0;
}

4. 超时连接释放测试 3

业务处理超时,查看服务器的处理情况。

当服务器达到了一个性能瓶颈,在一次业务处理中花费了太长的时间(超过了服务器设置的非活跃超时时间)。

在一次业务处理中耗费太长时间,导致其他的连接也被连累超时,其他的连接有可能会被拖累超时释放。

假设现在 12345 号描述符就绪了,在处理 1 的时候花费了 30s 处理完,超时了,导致 2345 描述符因为长时间没有刷新活跃度。

  1. 如果接下来的 2345 描述符都是通信连接描述符,如果都就绪了,则并不影响,因为接下来就会进行处理并刷新活跃度。
  2. 如果接下来的 2 号描述符是定时器事件描述符,定时器触发超时,执行定时任务,就会将 345 描述符给释放掉。这时候一旦 345 描述符对应的连接被释放,接下来在处理 345 事件的时候就会导致程序崩溃(内存访问错误)。因此这时候,在本次事件处理中,如果有释放连接的操作,并不能直接对连接进行释放,而应该将释放操作压入到任务池中,等到事件处理完了执行任务池中的任务的时候,再去释放。
#include "../source/server.hpp"
int main(){
    signal(SIGCHLD, SIG_IGN);
    for(int i = 0; i < 10; i++){
        pid_t pid = fork();
        if(pid < 0){
            LOG_DEBUG("FORK ERROR");
            return -1;
        }else if(pid == 0){
            Socket cli_sock;
            cli_sock.CreateClient(8080, "127.0.0.1");
            std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
            while(1){
                assert(cli_sock.Send(req.c_str(), req.size())!=-1);
                char buf[1024]={0};
                assert(cli_sock.Recv(buf,1023));
                LOG_DEBUG("[%s]", buf);
            }
            cli_sock.Close();
            exit(0);
        }
    }
    while(1)sleep(1);
    return 0;
}

现在把所有事件处理结束了,释放连接的操作都先压入到任务队列中。等到所有就绪事件处理完成后,在去执行任务队列中的任务。因此 Channel 中 Handevent 函数内,不用每个事件执行前先去执行任意事件回调。而是在最后执行一次任意事件回调。反正在处理就绪事件不会释放连接,不用担心因为释放连接销毁 Connection 对象而导致调用任意事件回调导致程序奔溃。

5. 数据中多条请求处理测试

一次性给服务器发送多条数据,然后查看服务器的处理结果。 预期结果:每一条请求都应该得到正常处理。

#include "../source/server.hpp"
int main(){
    Socket cli_sock;
    cli_sock.CreateClient(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    req += "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    req += "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    while(1){
        assert(cli_sock.Send(req.c_str(), req.size())!=-1);
        char buf[1024]={0};
        assert(cli_sock.Recv(buf,1023));
        LOG_DEBUG("[%s]", buf);
        sleep(3);
    }
    cli_sock.Close();
    return 0;
}

6. PUT 大文件上传测试

大文件传输测试,给服务器上传一个大文件,服务器将文件保存下来,观察处理结果。 预期结果:上传的文件,和服务器保存的文件一致。

dd if=/dev/zero of=./hello.txt bs=100M count=3 #创建一个大小为 300M 的文件
#include "../source/http/httpserver.hpp"
int main(){
    Socket cli_sock;
    cli_sock.CreateClient(8080, "127.0.0.1");
    std::string req = "PUT /1234.txt HTTP/1.1\r\nConnection: keep-alive\r\n";
    std::string body;
    Until::ReadFile("./hello.txt", &body);
    req += "Content-Length: " + std::to_string(body.size()) + "\r\n\r\n";
    assert(cli_sock.Send(req.c_str(), req.size())!=-1);
    assert(cli_sock.Send(body.c_str(), body.size())!=-1);
    char buf[1024]={0};
    assert(cli_sock.Recv(buf,1023));
    LOG_DEBUG("[%s]", buf);
    sleep(3);
    cli_sock.Close();
    return 0;
}

7. 服务器性能测试

采用 webbench 进行服务器性能测试。 Webbench 是知名的网站压测工具,它是由 Lionbridge 公司开发。

webbench 的标准测试可以向我们展示服务器的两项内容:每秒钟响应请求数和每秒钟传输数据量。

webbench 测试原理是,创建指定数量的进程,在每个进程中不断创建套接字向服务器发送请求,并通过管道最终将每个进程的结果返回给主进程进行数据统计。

./webbench -c 1000 -t 60 http://127.0.0.1:8080/hello
  • c: 指定客户端数量
  • t: 指定时间

性能测试的两个重点衡量标准:并发量 & QPS

并发量:可以同时处理多少客户端的请求而不会出现连接失败 QPS:每秒钟处理的包的数量

脱离具体环境讨论性能测试是不科学的!

测试环境: 服务器是 2 核 2G 带宽 4M 的云服务器 客户端是 ubuntu 环境 使用 webbench 以 1000 并发量,向服务器发送请求,进行了 60 秒测试 最终得到的结果是:并发量当前是 1000 包,QPM 1 分钟处理 215188 个包,QPS:一秒钟处理 3586 个包。

目录

  1. 服务器边缘测试与性能测试
  2. 1. 长连接连续请求测试
  3. 2. 超时连接释放测试 1
  4. 3. 超时连接释放测试 2
  5. 4. 超时连接释放测试 3
  6. 5. 数据中多条请求处理测试
  7. 6. PUT 大文件上传测试
  8. 7. 服务器性能测试
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 在 Jetson 上部署 OpenClaw 并接入飞书机器人实现远程交互
  • 在 IntelliJ IDEA 中修改 Git 远程仓库地址
  • 计算机网络基础知识详解:OSI 与 TCP/IP 模型
  • Stable Diffusion 云端版部署与个性化绘本生成指南
  • AIGC 时代如何利用 DeepSeek 辅助孩子学习编程
  • 解决 PKIX path building failed:SSL 证书导入 Java 信任库实战
  • Web1.0 到 Web3.0:互联网三次进化解析
  • Spring Boot 数据仓库与 ETL 工具集成实践
  • 腾讯混元图像 3.0 图生图模型开源,LMArena 评测跻身全球第一梯队
  • Python 自动化实战:wxauto 安装异常处理与核心功能详解
  • JavaScript 基础语法与核心概念详解
  • 前端实现视频画中画功能 - 主页面与小窗同步控制
  • Soft Actor-Critic (SAC) 算法详解与 PyTorch 实现
  • 基于 JsPDF 和 html2canvas 实现前端图表与列表数据多格式导出
  • C++ 仿函数详解:对象像函数一样调用
  • 分布式文件系统 HDFS 存储原理
  • 前端三年职业复盘:从传统软件到互联网实战
  • 一次红队渗透实战项目记录
  • Better Exceptions:Python 异常调试可视化工具
  • Claude Code 进阶指南:使用 Everything 插件打造有记忆的 AI 程序员

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online