Webserver项目学习
相关参考资料
牛客总结这个项目的面试提问点:
-
https://www.nowcoder.com/discuss/353159561039257600?sourceSSR=search
-
https://www.nowcoder.com/discuss/419276598265827328?sourceSSR=search
牛客视频教程:
微信公众号全套文章:
项目运行、测试、部署
实际部署所用的开源项目链接:
https://github.com/markparticle/WebServer
代码量不多,单个源文件最多不超过300行,有约10个源文件
-
有个人对这个项目的线程池实现进一步改进,提升了一些性能:
https://www.agedcat.com/post/4f05b258
https://github.com/markparticle/WebServer -
这个人还写了这个版本webserver的代码解析:
https://www.agedcat.com/post/4f05b258 -
其他一些版本WebServer的项目地址:
https://github.com/qinguoyi/TinyWebServer、
https://github.com/linyacool/WebServer/tree/master
部署平台和相关环境
- 腾讯云服务器ubuntu 18.04 LTS
- mysql 5.7.41(ubuntu 18.04默认安装这个版本)
坑:一开始用的是ubuntu 20.4,默认安装mysql 8,然后配置mysql账户密码时不能使用webserver相关代码。
坑:还用了wsl尝试部署,但是同样的操作,最后运行make出的文件,项目会出奇怪的bug,无法正常启动
mysql安装与配置
参考:
https://segmentfault.com/a/1190000023081074
- 安装mysql的三个东西:
//本体,真正的mysql服务器
sudo apt-get install mysql-server
//mysql命令行客户端,提供mysql -u root -p这种功能的
sudo apt-get install mysql-client
//编程用到的静态文件、链接库等,例如项目中用到的mysql.h
sudo apt-get install libmysqlclient-dev
- 更改密码,目的是创造一个默认的root用户,使得可以在命令行登录
mysql -u root -p。先查看目前mysql默认安装情况下的用户名和密码配置:
sudo cat /etc/mysql/debian.cnf
- 用查到的密码登录mysql:
//查到的密码为:
password=xxxxxxxxxx
//查到的用户名为:
debian-sys-maint
//登录:
mysql -u debian-sys-maint -p
//输入上面查到的密码
- 成功登录mysql后,需要修改密码:
use mysql;
// 下一行,密码改为了yourpassword,可以设置成其他的
update mysql.user set authentication_string=password('yourpassword') where user='root' and Host ='localhost';
update user set plugin="mysql_native_password";
flush privileges;
quit;
坑:
一开始用的是ubuntu 20.4,默认安装mysql 8,然后配置mysql账户密码时不能使用上面的相关代码,还把mysql弄的无法登陆了。最终重装ubuntu 18.04完全复刻原始项目配置才成功。
- 修改完密码之后,重启mysql服务并用新设置的root用户登录。若成功,说明mysql已经安装并配置完毕
sudo service mysql restart
mysql -u root -p 新密码
项目初始化并运行
- 初始化mysql用户表,这个表用来存储网站的合法登录用户。
// 建立yourdb库
create database yourdb;
// 创建user表
USE yourdb;
CREATE TABLE user(
username char(50) NULL,
password char(50) NULL
)ENGINE=InnoDB;
// 添加数据
INSERT INTO user(username, password) VALUES('name', 'password');
- 将项目从github clone下来
国内服务器由于网络关系,访问github速度慢且不稳定,可使用一些中间代理加速:
//原始clone链接
git clone https://github.com/markparticle/WebServer.git
//加速clone链接
git clone https://gitclone.com/github.com/markparticle/WebServer.git
参考:https://cloud.tencent.com/developer/article/1744627
vim修改主函数中相关的数据库用户名、数据库密码、项目要部署到的网络端口
一次使用vim修改main.cpp的基础流程:
#使用vim打开目标文件
vi main.cpp
sudo vi main.cpp //在wsl中,文件通常是只读,权限不够时需要修改文件就要加sudo
#打开文件以后按i进行insert,开始修改目标文件
i
#键盘上的pageup,pagedown可以帮助快速翻页
#编辑完成以后保存并退出
esc //先退出编辑模式,进入操作模式
:q //不保存直接退出
:wq //保存并退出
main.cpp:
/*
* @Author : mark
* @Date : 2020-06-18
* @copyleft Apache 2.0
*/
#include <unistd.h>
#include "server/webserver.h"
int main() {
/* 守护进程 后台运行 */
//daemon(1, 0);
WebServer server(
1316, 3, 60000, false, /* 端口 ET模式 timeoutMs 优雅退出 */
3306, "root", "root", "webserver", /* Mysql配置 */
12, 6, true, 1, 1024); /* 连接池数量 线程池数量 日志开关 日志等级 日志异步队列容量 */
server.Start();
}
上面需要修改的部分:
WebServer server(
1316, 3, 60000, false, /* 这里的1316就是我们要部署到的端口
3306, "root", "root", "webserver",
/* Mysql配置 第一个参数:默认localhost连接端口,第二个参数:要使用的mysql登录用户名,第三个参数:要使用的mysql登录用户的密码 */
12, 6, true, 1, 1024); /* 连接池数量 线程池数量 日志开关 日志等级 日志异步队列容量 */
生成可执行项目的文件并运行项目
使用make工具编译链接项目中的代码文件,生成可执行文件server
- 在项目根目录下运行
make
- 执行上一步make中生成的可执行文件
server
./bin/server
上述过程发生了什么?
-
在项目根目录下
make:这将会使用根目录下Makefile中的配置进行make操作
/Makefile:
all:
mkdir -p bin
cd build && make
可以看到,makefile中其实就是提前写好的shell指令集合
第一步,创建bin文件夹;第二步,进入build文件夹并在build下执行make
- 让我们继续看看build下的make在干嘛:
/build/Makefile:
CXX = g++
CFLAGS = -std=c++14 -O2 -Wall -g
TARGET = server
OBJS = ../code/log/*.cpp ../code/pool/*.cpp ../code/timer/*.cpp \
../code/http/*.cpp ../code/server/*.cpp \
../code/buffer/*.cpp ../code/main.cpp
all: $(OBJS)
$(CXX) $(CFLAGS) $(OBJS) -o ../bin/$(TARGET) -pthread -lmysqlclient
clean:
rm -rf ../bin/$(OBJS) $(TARGET)
可以看到,这是在编译源文件,生成TARGET = server,其中c++使用c++14版本,编译器为g++之类的。
使用浏览器测试部署好的项目
在浏览器中输入
云服务器公网ip:项目部署的port
我这里的port为1316(端口配置写在根目录的main.cpp中,可通过vim自行修改)
服务器防火墙/安全组设置
如果对服务器使用经验不足或者计算机网络敏锐度差一些,很可能意识不到这个问题,在云服务器上部署并运行server可执行文件以后,启动项目的bash进程进入阻塞,暗示项目跑起来了,但是自己用个人电脑访问(云服务器公网ip:项目部署的port)却拿不到http响应。
对于云服务器,每个向外暴露的端口都要设置在防火墙里,否则外界无法访问,因此为程序需要的端口设置防火墙.
在腾讯云服务器的防火墙配置中,添加
端口为1316,连接方式为TCP的新规则
然后使用个人电脑浏览器(比如自己的windows笔记本)访问(云服务器公网ip:项目部署的port)。观察到:浏览器成功拿到了http响应。
403问题
单元测试
cd test
make
./test
压力测试
./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 5000 -t 10 http://ip:port/
./webbench-1.5/webbench -c 10000 -t 10 http://ip:port/
自己修改原有项目并开发:
vscode连接、可能需要虚拟机和xshell,不确定如何用vscode连接云服务器?
https://shenshenzhou.xyz/posts/MyWebServer-development/
项目主要模块学习
基于EPOLL和线程池的高并发IO模型
利用IO复用技术Epoll与线程池实现多线程的Reactor高并发模型;
基于正则与状态机的HTTP解析器
利用正则与状态机解析HTTP请求报文,实现处理静态资源的请求;
基于标准化容器的缓冲区
利用标准库容器封装char,实现自动增长的缓冲区;
基于小根堆的定时器
基于小根堆实现的定时器,关闭超时的非活动连接;
基于单例模式与阻塞队列的异步日志系统
利用单例模式与阻塞队列实现异步的日志系统,记录服务器运行状态;
基于RAII机制的数据库连接池
利用RAII机制实现了数据库连接池,减少数据库连接建立与关闭的开销,同时实现了用户注册登录功能。
测试单元
增加logsys,threadpool测试单元(todo: timer, sqlconnpool, httprequest, httpresponse)
张小方:聊webserver作为面试项目的事情
他的个人主页:
https://github.com/balloonwj/CppGuide
我用的这个著名的webserver项目好像很多低级错误
反思:学习gdb调试、做更多的linux项目以熟悉各种linux开发工具,也有助于了解底层。选择高质量的资料很重要,如果今天没有看张小方讲webserver,我又可能浪费很多时间来调这个低质量的webserver。高质量课程和资料往南大操作系统、南大计算机系统课程、6.824上靠。
下个阶段的计划:
- 维持一个好用的博客系统,自己长期坚持使用,定期把目前的文章迁移过去,用go语言
- 写一个硬核的大项目。go语言
- 高质量课程和资料往南大操作系统、南大计算机系统课程、6.824
- C++ webserver和量化交易系统项目作为量化岗位的敲门砖
浙公网安备 33010602011771号