webtinyserver讲解
---------
能帮到你的话,就给个赞吧 😘
********
服务器分析与设计
服务器的工作
要分析,首先得知道服务器都干什么。
服务器所需工作:
- 检测套接字有无io
- 进行io
- 业务处理
class Server {
private:
public:
void run();
};
void Server::run() {
//1.检测套接字有无io //检测套接字集合,返回有io的套接字集合withIoSocks
epoll / poll / select(socks, timeout); //无须知道epoll/poll/select是什么,只须知道它们是检测套接字io一种方法即可
for (oneIoSock = withIoSocks.begin(); oneIoSock != withIoSocks.begin(); oneIoSock++) {
//2.进行io //一个io
io(oneIoSock);
//3.业务处理 //处理一个业务
businessProcess(oneBusiness);
}
}
//入口线程
int main() {
Server server();
server.run();
}
但是很明显,上述代码有严重的效率问题。
- businessProcess必须等io执行完
也就是依赖或者叫同步,但不重要,重要的是我们明显不想这样做
可以解耦的关键?
操作的依赖到底是数据还是操作
两个场景,饭堂与快递柜
饭堂喊号:
顾客的身份是相对饭而言。饭是7 你也是7
处理http请求
1.解析
2.根据url和请求体做相应的处理
3.生成响应
4.注册监听
定时器
使用信号实现定时器
进程与信号
进程可以向系统注册一些进程需要处理的信号。这样,当注册的信号发生时,系统会中断进程,进程执行信号处理函数。
多线程时,系统将会随机发送一个信号给线程。
信号并发时,暂写
sigaction结构体
默认用sa_handler,若sa_flags设置SA_SIGINFO,则用sa_sigaction。
sa_mask:线程执行信号处理时,屏蔽sa_mask中的信号(不会再被中断)。待执行完后,再处理屏蔽间发生的信号。若某信号屏蔽间发生多次,也只处理一次。
定时信号-alarm
alarm(n);n秒后向进程发送定时信号SIGALRM
信号处理流程-统一处理
信号处理函数是随机一个线程执行的,如果想统一由主线程处理,则可以通过管道和epoll实现。
线程接收信号并不做处理,而是将信号发送给主线程,主线程再做处理。
具体的
主线程循环触发定时信号,信号处理函数并不做处理,而是通过管道pipe[0]发送给pipe[1],而pipe[1]是添加到epoll中的,所以,主线程可以通过epoll统一监听处理。
定时器设计
定时器并非是倒计时,而是正计时。例如倒计时5秒,并不是5减到0,而是当前时刻往后加5秒,例如当前1秒,倒计时5秒,则截止时间为6秒。然后再检查当前时间是否>6秒,大于则超出倒计时,小于则未超出。当然检查并非每时每刻都检查,而是隔一段时间一检查。例如5秒,可以隔一秒一检查。也就是alarm(1)。
定时器可以说就一个东西,截止时间。
然而我们要一次检查所有定时器,也就是容器的设计,要快速地筛出超时定时器。
webtinyserver中用的是升序链表。
简单概括
循环触发alarm(n),然后检查定时器是否超时。
由此可见,定时器设计本身和alarm无关系,而alarm的作用也仅是检查的频率。
待解决问题:
并发模型缺点-半同步半反应堆:
- 双缓冲对列
- 工作线程少
3.定时器优化
4.数据库连接封装
5.优化整体代码
开发问题:
1.epoll et/le 与 套接字 阻塞非阻塞关系
2.生产者消费者-条件变量模型
3.请求对列存函数对象
4.解析失败时怎么做
5.epoll监听一次后还要重新注册才能再监听吗
参考:
解耦、削峰、异步的理解_异步削峰解耦_咯噔哟的博客-CSDN博客