# TinyHttpServer **Repository Path**: susocket/tiny-http-server ## Basic Information - **Project Name**: TinyHttpServer - **Description**: 基于Linux,使用C++语言构建的轻量级HTTP服务器。 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 11 - **Created**: 2022-10-17 - **Last Updated**: 2022-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WebServer项目详解 用C++实现的高性能WEB服务器 #### 功能 - 利用I/O多路复用技术的`Epoll`与`线程池`实现【单Reactor、多线程】的高并发服务器模型; - 利用有限状态机解析HTTP请求报文,支持解析GET和POST请求; - 利用STL标准库容器封装char,实现自定义的缓冲区; - 基于堆结构实现的定时器,关闭超时的非活跃网络连接; - 支持用户注册登录功能,实现了数据库连接池,减少连接建立和关闭的开销。 - 使用缓冲区技术实现了简单的异步日志系统 #### 项目详解 [WebServer项目——webserver详解](/docs/mds/webserver.md) [WebServer项目——httpconnect详解](/docs/mds/httpconnect.md) [WebServer项目——buffer详解](/docs/mds/buffer.md) [WebServer项目——epoller详解](/docs/mds/epoller.md) [WebServer项目——timer详解](/docs/mds/timer.md) [WebServer项目——threadpool详解](/docs/mds/threadpool.md) [WebServer项目——MySQL数据库使用详解](/docs/mds/mysql.md) [WebServer项目——日志库Log详解](/docs/mds/log.md) #### 环境要求 - Linux - C++11 - MySQL #### 项目启动 拷贝整个项目文件,在终端中使用 ```cpp // 编译程序 ./autobuild.sh /* ./可执行文件名 端口号 定时时间 触发模式 线程数量 日志等级 */ ./myserver 9999 60 1 8 3 ``` 配置MySQL数据库,导入webserver库([具体过程](/docs/mds/mysql.md)) #### 性能表现 **压力测试** ```cpp ./webbench-1.5/webbench -c 10 -t 10 http://ip:port/ ./webbench-1.5/webbench -c 100 -t 10 http://ip:port/ ./webbench-1.5/webbench -c 1000 -t 10 http://ip:port/ ./webbench-1.5/webbench -c 10000 -t 10 http://ip:port/ ``` - 测试环境:Ubuntu18, CPU i7-9700 3.00GHz, 内存 16GB 用我自己的测试环境跑了一下 ![压力测试截图](docs/img/性能测试最好结果.png) | | 10 | 100 | 1000 | 10000 | | :--------------: | :---: | :---: | :---: | :---: | | 日志关、定时检测关 | 12184 | 14171 | 14443 | 17010 | | 定时检测关 | 8021 | 8250 | 8102 | 7586 | | 日志关 | 8449 | 10119 | 9889 | 9491 | 在关闭日志、关闭定时检测的模式下,对LT和ET模式进行测试 | listenFd、connectFd | 10 | 100 | 1000 | 10000 | | :--------------: | :---: | :---: | :---: | :---: | | LT+ET | 8539 | 9480 | 11287 | 17010 | | LT+LT | 8462 | 9992 | 9945 | 8770 | | ET+ET | 8358 | 9107 | 9346 | 7981 | | ET+LT | 8411 | 9552 | 9451 | 8283 | **QPS对比** 【[markparticle](https://github.com/markparticle/WebServer/)】和【[老猫轩仔](https://www.agedcat.com/programming_language/cpp/537.html)】的web服务器,并将测试情况记录如下表 | | 10 | 100 | 1000 | 10000 | | :--------------: | :---: | :---: | :---: | :---: | | [markparticle](https://github.com/markparticle/WebServer/) | 4657 | 4624 | 4549 | 4225 | | [老猫轩仔](https://www.agedcat.com/programming_language/cpp/537.html) | 13530 | 13690 | 13688 | 12345 | | [本项目](https://github.com/IRVING-L/HttpServer) | 12184 | 14171 | 14443 | 17010 | *横坐标为并发客户端数量;表格数据为QPS,单位page/s* **总结:** - 从上面表中数据可以发现,增加【定时检测非活跃连接】和【日志输出模块】,大大降低了服务器的性能表现。 - LT+ET的模式更加适合于web服务器,在高并发的情况下性能表现是最好的。 - 从数据上来看,Web服务器单机性能最高可以达到1w+(本项目最高可达2w)的QPS。如果想要进一步提高性能,一方面是抠代码细节,另一方面就只能是多机组合使用Nginx代理了。 #### 更新日志 - [x] 解决服务器发送大文件的Bug - 在wirtev分散写函数中,每一次发送数据后,要能及时的更新iov结构的指针,这样就能实现服务器上发送大文件的功能。 - [x] 增加请求视频文件的页面 - 视频文件也是文件,和图片文件一样发送即可。 - [x] 完善locker.h中的封装类,统一使用该同步机制 - 项目中,所用到的同步机制,均采用该封装类(信号量的封装) - [x] 改进代码结构,更新局部变量懒汉单例模式 - [x] main函数封装重构 - [x] 新增命令行日志开关,关闭日志后更新压力测试结果 - [x] 改进编译方式,只配置一次SQL信息即可 - [x] 实现数据库连接池信号量与代码结构 - [x] 使用RAII机制优化数据库连接的获取与释放 - [x] 解决了项目性能下降的问题 - [x] 增加日志库输出级别,在启动程序时输出参数设定,低于设定级别的日志不会被输出 - [x] 优化代码结构,封装工具类以减少全局变量 - [x] 编译一次即可,命令行进行个性化测试更加友好 - [x] 实现非阻塞模式下的ET和LT触发,并完成压力测试 - 客户端的连接设置为LT或者ET,对于压力测试的影响应该是很小的(一个HTTP请求,一次就可以读完,LT模式下也不会多次提醒)。触发模式对于监听的socket是有一定影响的,LT相对来说是好一点的。 - [x] 优化HTTP解析方式,使用C指针解析请求报文,替换之前的C++正则运算符`regex` - 正则运算符解析代码清晰,解析灵活,缺点是速度慢; - 使用C字符串函数+指针操作可以大幅提高解析速度 - [ ] 实现服务器接收不定长度的大文件 - [ ] 实现HTTPS加密传输 - [ ] 解决数据库同步校验内存泄漏 - [ ] 新增Proactor模式,并完成压力测试 #### 致谢 @[老猫轩仔](https://www.agedcat.com/programming_language/cpp/537.html) @[markparticle](https://github.com/markparticle/WebServer/)