Webserver项目学习

相关参考资料

牛客总结这个项目的面试提问点:

牛客视频教程:

微信公众号全套文章:

项目运行、测试、部署

实际部署所用的开源项目链接:
https://github.com/markparticle/WebServer

代码量不多,单个源文件最多不超过300行,有约10个源文件

部署平台和相关环境

  • 腾讯云服务器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

  1. 安装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 
  1. 更改密码,目的是创造一个默认的root用户,使得可以在命令行登录mysql -u root -p。先查看目前mysql默认安装情况下的用户名和密码配置:
sudo cat /etc/mysql/debian.cnf
  1. 用查到的密码登录mysql:
//查到的密码为:
password=xxxxxxxxxx
//查到的用户名为:
debian-sys-maint
//登录:
mysql -u debian-sys-maint -p
//输入上面查到的密码
  1. 成功登录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完全复刻原始项目配置才成功。
  1. 修改完密码之后,重启mysql服务并用新设置的root用户登录。若成功,说明mysql已经安装并配置完毕
sudo service mysql restart 
mysql -u root -p 新密码

项目初始化并运行

  1. 初始化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');
  1. 将项目从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

  1. 在项目根目录下运行
make
  1. 执行上一步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上靠。

下个阶段的计划:

  1. 维持一个好用的博客系统,自己长期坚持使用,定期把目前的文章迁移过去,用go语言
  2. 写一个硬核的大项目。go语言
  3. 高质量课程和资料往南大操作系统、南大计算机系统课程、6.824
  4. C++ webserver和量化交易系统项目作为量化岗位的敲门砖

面试问题准备

posted @ 2023-04-30 21:34  wjybq  阅读(1483)  评论(2)    收藏  举报