RabbitServer

2025-12-07 0 310

介绍

RabbitServer是一个运行于GNU/Linux平台的HTTP服务器,采用C++14编写,目前支持处理HTTP/1.1的静态GET,HEAD,OPTIONS请求以及FastCGI请求。

特点

  1. 基于半同步半异步的reactor模型
  2. 使用epoll边缘触发的IO多路复用技术
  3. 使用独创无锁事件分发模型
  4. 支持长连接,采用Timerfd支持以事件驱动的多轮盘Timewheel,以实现应用层TCP保活机制
  5. 基于双缓冲区技术细粒度锁实现的线程安全hashmap实现了简单的异步日志系统
  6. 大量利用析构函数,智能指针等手段实现RAII机制,无内存泄露
  7. 实现基于状态机的HTTP解析
  8. 实现Fastcgi协议与后台运行的php-fpm进行通信
  9. 使用非阻塞connect实现简单客户端,支持用户态重连
  10. 实现安全高效的用户态InputBufferOuputbuffer,以保证服务器的高可用性
  11. 解决busy_loop问题
  12. 为保证高性能在发送文件时使用零拷贝技术
  13. 引入绑核机制最大化CPU缓存命中率
  14. 引入tcmalloc优化内存分配
  15. 大量应用constexper,noexcept,__attribute__等机制以增加代码的优化潜能
  16. 在性能分析过后引入套接字slab层,最小化内存分配,提高性能
  17. 引入全局无锁队列,实现基于吞吐量和每线程长连接数量的特殊加权轮询负载均衡算法
  18. 尝试引入内核5.1版本新特性io_uring以提升框架性能,已封装完成,但在抉择后放弃引入
  19. 整个项目各个子版块交互设计优良且子版块之间松耦合,使得维护与优化更为简洁
  20. 运行简单且稳定,直接在后台执行即可,且就测试而言相比于Nginx与Apache请求完成时间波峰不明显且无失败请求,即运行非常稳定

安装与运行

运行RabbitServer之前首先要确保你的机器已经正确配置了Cmake,你可以在软件源中下载并安装Cmake。

# debian && ubuntu
sudo apt-get install cmake

# arch
sudo pacman -S cmake

确保你的机器安装GCC,并支持c++14(最低6.0版本)你可以点击这里查看GCC对C++特性的支持。

# arch
sudo pacman -S gcc

其他版本Linux比较繁琐,具体操作点击
传送门

最后确保你的机器已经预安装了boost库。

wget http://s*our**ceforge.net/projects/boost/files/boost/1.54.0/boost_1_54_0.tar.gz
tar -xzvf boost_1_54_0.tar.gz
cd boost_1_54_0
./bootstrap.sh --prefix=/usr/local
sudo ./b2 install --with=all

因为加入了性能分析和tcmalloc,所以需要引入gperftools工具。

# arch 
sudo pacman -S gperftools
# 其他版本
./autogen.sh
./configure
make -j8
sudo make install
ldconfig 刷新动态库文件

这里安装完成以后会出现一个问题,就是gperftools产生的动态库在/usr/local/lib中,而这并不在系统动态库的默认查找路线。一种可行的方法是修改/etc/ld.so.conf,在文件尾部加入/usr/local/lib。

性能测试如果需要生成pdf的话需要安装Graphviz。

# debian && ubuntu
sudo apt-get install graphviz graphviz-doc

# arch
sudo pacman -S graphviz

最后为了提升性能引入了io_uring,但是最终并没有使用,所以如果机器内核版本低于5.1或者机器并未安装liburing的话可以删除RabbitServer/src/net/iouring*,如果想尝试liburing的使用可以尝试编译。

目前arch的软件源中已经更新了liburing,arch玩家可以在软件源中直接下载并安装liburing,但是debian系的apt-get和苹果的homebrew都没有上线。所以只能自己编译安装了。当然版本低于5.1就只能安装新版本内核,这就比较麻烦了。

# arch
sudo pacman -S liburing

# 其他
wget  https://github*.c**om/axboe/liburing/archive/liburing-0.2.zip
unzip liburing-0.2.zip
cd liburing-liburing-0.2/
./configure --libdir=/usr/lib64 
make CFLAGS=-std=gnu99 && make install

以上步骤完成以后我们就可以运行RabbitServer了。

# 以下是标准的运行方式,允许创建的文件夹为其他名称,不这样的执行话reaprovider.cc中line 103文件打开可能出现问题;
mkdir build;
cd build;
cmake ..;
make;
./Web_Server;

目录结构说明

.
├── image
│   ├── FistEdition     // 第一版性能测试 fbf3e80
│   ├── SecondEdition   // 第二版性能测试 e60f4af
│   └── class.png       // 类图
└──src
    ├── base            // 基础类与配置
    ├── client          // 客户端主体相关
    ├── FastCgi         // FastCgi相关
    ├── http
    │   ├── provider    // 提供http响应报文
    │   └── other       // 解析http请求报文
    ├── log             // 异步日志库
    ├── net             // 对于epoll与套接字的封装
    ├── server          // 服务器主体相关
    └── tool            // 向其他目录提供耦合子模块的封装

测试环境

环境名称
系统 5.9.6-arch1-1
处理器 4 x Intel® Core i5-7200U CPU @ 2.50GHz
L1 Cache 32KB
逻辑核数 4
系统负载 1.72, 1.89, 1.99
内存占用 5238.8MB(used)/2292.2MB(buff/cache)/209.6MB(free)
Swap 2268.8MB(used)/5923.2MB(free)
Cmake版本 3.18.4
GCC版本 10.2.0

测试项目 ApacheBench v2.3

对比对象: Nginx 1.18.0-2 / Apache Httpd/2.4.46-3

测试所使用的命令:

ab -n 100000 -c 100  127.0.0.1:8888/ (80)

每秒完成的请求数(RPS):

服务器名称 值/sec
Nginx 23505.79
RabbitServer 20764.96
Apache 16887.30

每个请求花费的时间:

服务器名称 值/ms
Nginx 0.043
RabbitServer 0.048
Apache 0.059

百分比请求完成时间(连接时长 + 服务器处理时长 + 一个RTT):

百分比 Nginx/ms RabbitServer/ms Apache/ms
50% 5 5 6
66% 5 5 6
75% 5 5 6
80% 5 5 6
90% 6 6 7
95% 5 6 7
98% 6 6 10
99% 6 9 14
100% 16 37 54

测试所使用的命令:

ab -n 1000000 -c 1000 -r 127.0.0.1:8888/ (80)

添加-r参数的原因

每秒完成的请求数(RPS):

服务器名称 值/sec
Nginx 18103.65
RabbitServer 19288.36
Apache 15406.28

每个请求花费的时间:

服务器名称 值/ms
Nginx 0.055
RabbitServer 0.052
Apache 0.065

百分比请求完成时间(连接时长 + 服务器处理时长 + 一个RTT):

百分比 Nginx/ms RabbitServer/ms Apache/ms
50% 26 50 56
66% 28 53 61
75% 28 54 63
80% 29 54 65
90% 32 55 69
95% 37 57 73
98% 42 61 99
99% 50 67 263
100% 54072 1083 3280

总结 第一版(fbf3e809b34bb266c03fbe5cc9a7e67bdc942cd6)

从性能分析角度

就性能分析结果来看,RabbitServer的架构是没有大问题的,因为最为耗CPU时长的函数就是send,sendfile,close这些正常的大消耗系统调用,正常的逻辑处理其实没有什么特殊的地方。

但是有一个地方令人诧异,就是unique_ptr的各种操作耗时,占到了整个项目运行时CPU占有率的百分之十二以上,这是令人十分震惊的,因为在1000线程时RabbitServer的RPS已经超过了Nginx,而在100线程时比Nginx低百分之八左右,这是一个后面要着重思考的地方,其他的地方就性能分析图来看没有什么问题。

当然我选择的架构不是最优的,就目前来说还是ReusePort加多线程(多进程)处理的方法更为优秀,不仅是因为单点的accept瓶颈问题,而是因为内核可以自动做到负载均衡。单线程accept多线程处理的模型做起负载均衡来就比较麻烦,尤其是支持长连接的时候,这是一个后期可以改进的点,目前已经有了大概的构思。

还有本来想在文件的代理类部分引入一层类slab层,这样静态的资源就免去了不停的打开关闭,我们只需要打开一次,后面改变偏移量就可以了,担心资源浪费的话可以引入LRU或者LFU,但分析以后发现文件的操作并没有消耗太长的时间,所以遵循二八法则,暂时没有这样做。

最后一点,unordered_map.erase操作非常慢,占到了全部时间的百分之10左右,这启发我们可以在fd层面复用对象,因为描述符是有限的,而map仅仅使用int作为键,所以可想的,这种做法一定可以大幅度提升效率。

从CPU负载角度

首先来看看RabbitServer在运行时的CPU负载情况:

这个情况很好理解,也符合预期,因为ApacheBench使用的是HTTP 1.0,所以只支持短连接,且请求内容都一样,所以每个核的负载其实很平均,accept线程相对来说负载较轻,所以CPU3负载较低。

这里我尝试过把工作线程的数量提高一点,但是可见的工作线程一定会与accept线程竞争,为了减轻accept线程破坏多个工作线程缓存的有效性,我引入了绑核机制,使得accept线程只会和一个工作线程竞争,因为就性能分析图可以看出简单的http请求处理其实是计算密集型,所以缓存的失效比想象的更严重,加工作线程这个决定直接使得整体的RPS下降了百分之十八。

所以这也可以看出这样的模型说起来会有accept的单点问题,实际也确实出现了这样的问题,在一百万请求的压测下,accept线程的空闲CPU比也仅剩百分之十,我们可以看到accept的软中断和内核空间的消耗非常大,这很好理解,因为它需要一百万次的accept和大量的epoll_wait,这也是再加一个工作线程整体RPS下降如此之大的主要原因,四核的机器已经是如此,更不必说再更高的核了,过两天借毅毅12核机器测试一下。

其实从负载看出的最大问题就是用户态消耗的时间太长,理论来说好的服务器应该大多数的时间消耗在内核态,这意味着更高效率的处理请求,因为用户态逻辑较少,但是第一版可以看出用户态占用时间过长。


经过一段时间针对性的性能优化,可以看到基本耗时较长的消耗都集中在开销较大的系统调用了,这也是理想中的情况:

后续可以修改的地方

  1. 搞清楚以后替换unique_ptr
  2. FastCgi的请求目前还是同步,最近时间太紧,有时间可以修改为异步,目前已经构思了两种方案。
  3. HEAD,OPTIONS还没加呢,别忘了。
  4. 基于偷盗队列的负载均衡,需要多线程之间epoll安全的转移套接字,目前想到一种\”五次握手\”方法,但是还没有实施.

4. 添加负载均衡

5. 添加套接字slab层

下载源码

通过命令行克隆项目:

git clone https://github.com/Super-long/RabbitServer.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 RabbitServer https://www.zuozi.net/31886.html

fastkiss
上一篇: fastkiss
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务