Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update design doc #143

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions 并发模型.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,21 @@ epoll的触发模式在这里我选择了ET模式,muduo使用的是LT,这两

每个SubReactor持有一个定时器,用于处理超时请求和长时间不活跃的连接。muduo中介绍了时间轮的实现和用stl里set的实现,这里我的实现直接使用了stl里的priority_queue,底层是小根堆,并采用惰性删除的方式,时间的到来不会唤醒线程,而是每次循环的最后进行检查,如果超时了再删,因为这里对超时的要求并不会很高,如果此时线程忙,那么检查时间队列的间隔也会短,如果不忙,也给了超时请求更长的等待时间。

## 核心结构

程序中的每一个类和结构体当然都必不可少,其中能体现并发模型和整体架构的,我认为是有两个:

* Channel类:Channel是Reactor结构中的“事件”,它自始至终都属于一个EventLoop,负责一个文件描述符的IO事件,在Channel类中保存这IO事件的类型以及对应的回调函数,当IO事件发生时,最终会调用到Channel类中的回调函数。因此,程序中所有带有读写时间的对象都会和一个Channel关联,包括loop中的eventfd,listenfd,HttpData等。
* EventLoop:One loop per thread意味着每个线程只能有一个EventLoop对象,EventLoop即是时间循环,每次从poller里拿活跃事件,并给到Channel里分发处理。EventLoop中的loop函数会在最底层(Thread)中被真正调用,开始无限的循环,直到某一轮的检查到退出状态后从底层一层一层的退出。

## Log
## 核心结构设计

程序中的每一个类和结构体当然都必不可少,其中能体现并发模型和整体架构的,我认为是有下面几个类:
#### Server类
Server是http服务器的包装类,主要负责开启端口监听和启动事件主循环(Main Reactor),其中事件主循环会将新的客户端连接accept,并放入epoll监控的fd队列,交由后面EventLoop(Sub Reactor)来和客户端做socket读写通信(借助于Channel类)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one thread one loop 的含义更多是 one thread one reactor,这里可以着重介绍一下Server是如何组织多个reactor,如何分配事件到相应的reactor之中的,这个过程更能体现整体结构和并发来源

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

#### Channel类
Channel是Reactor结构中的“事件”,它自始至终都属于一个EventLoop,负责一个文件描述符的IO事件,在Channel类中保存这IO事件的类型以及对应的回调函数,当IO事件发生时,最终会调用到Channel类中的回调函数。因此,程序中所有带有读写事件的对象都会和一个Channel关联,包括loop中的eventfd,listenfd,HttpData等。
#### EventLoop
One loop per thread意味着每个线程只能有一个EventLoop对象,EventLoop即是事件循环,每次从poller里拿活跃事件,并给到Channel里分发处理。EventLoop中的loop函数会在最底层(Thread)中被真正调用,开始无限的循环,直到某一轮的检查到退出状态后从底层一层一层的退出。
#### HttpData类
HttpData是用来读写socket数据,转换解析http 协议的数据,并做对应的业务处理,具体的read/write handler在事件主循环接受新连接时,在HttpData的构造函数中传入,具体见
```
Server::handNewConn()
```
## 日志记录设计
Log的实现了学习了muduo,Log的实现分为前端和后端,前端往后端写,后端往磁盘写。为什么要这样区分前端和后端呢?因为只要涉及到IO,无论是网络IO还是磁盘IO,肯定是慢的,慢就会影响其它操作,必须让它快才行。

这里的Log前端是前面所述的IO线程,负责产生log,后端是Log线程,设计了多个缓冲区,负责收集前端产生的log,集中往磁盘写。这样,Log写到后端是没有障碍的,把慢的动作交给后端去做好了。
Expand Down