Muduo - Reactor模式

Muduo - Reactor模式

一、Reactor 是什么

wiki的中文定义:Reactor模式是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handler,这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。


从上述文字中我们可以看出以下关键点:

  1. 事件驱动(event handling)
  2. 可以处理一个或多个输入源(one or more inputs)
  3. 通过Service Handler同步的将输入事件(Event)采用多路复用分发给相应的Request Handler(多个)处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqMXsBTi-1590139303282)Muduo - Reactor模式_第1张图片(C:\Users\andyhkmo\Pictures\Saved Pictures\pic3.png)]

二、单线程Reactor模式

单Reactor单线程模式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uC8us57g-1590139303285)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic4.png)]Muduo - Reactor模式_第2张图片

简单代码如下

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  
server_socket.bind(('', 2007))  
server_socket.listen(5)  
# serversocket.setblocking(0)  
 
poll = select.poll() # epoll() should work the same  
connections = {}  
handlers = {}  
 
def handle_input(socket, data):  
	socket.send(data) # sendall() partial?  
 
def handle_request(fileno, event):  
	if event & select.POLLIN:  
		client_socket = connections[fileno]  
		data = client_socket.recv(4096)  
		if data:  
			handle_input(client_socket, data)  
		else:  
			poll.unregister(fileno)  
			client_socket.close()  
			del connections[fileno]  
			del handlers[fileno]  
 
def handle_accept(fileno, event):  
	(client_socket, client_address) = server_socket.accept()  
	print "got connection from", client_address  
	# client_socket.setblocking(0)  
	poll.register(client_socket.fileno(), select.POLLIN)  
	connections[client_socket.fileno()] = client_socket  
	handlers[client_socket.fileno()] = handle_request  
 
poll.register(server_socket.fileno(), select.POLLIN)  
handlers[server_socket.fileno()] = handle_accept  
 
while True:  
	events = poll.poll(10000) # 10 seconds  
	for fileno, event in events:  
		handler = handlers[fileno]  
		handler(fileno, event)  

最基本的单线程Reactor模型,程序的核心是事件循环,通过handlers转发到各个函数中去。

三、muduo Reactor模式

muduo是基于非阻塞的IO和事件驱动的网络库。

muduo的整体结构是one loop per thread+threadpool。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZqaGYcF-1590139303286)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic9.png)]Muduo - Reactor模式_第3张图片


muduo的事件驱动都是通过一个EventLoop来完成的。EventLoop一直处在事件循环中,通过IO复用机制poll/epoll回调激活的事件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39RZJVEe-1590139303288)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic5.png)]Muduo - Reactor模式_第4张图片

而muduo的Reactor主要由三部分组成,EventLoop、Poller、Channel。


  1. EventLoop即IO线程中的事件循环.它能确保所有注册的事件都在EventLoop对象所在的线程中执行,不用考虑事件的并发。它是线程安全的,且允许其他线程往EventLoop里面塞东西。

  2. Poller 是IO multiplexing的封装,它是EventLoop的组成,与EventLoop的生命期相当,为EventLoop提供poll()方法。

  3. Channel 每个Channel对象自始至终只负责一个文件描述符(fd)IO事件分发,但它不拥有这个fd,也不会在析构的时候关闭这个fd。每个Channel对象自始至终只属于一个EventLoop,因此每个Channel对象都只属于某一个IO线程。 Channel会把不同的IO事件分发为不同的回调, 例如ReadCallbackWriteCallback等。

EventLoop的时序图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LTmuUSrj-1590139303291)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic6.png)]Muduo - Reactor模式_第5张图片

具体实现代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VW0kROkN-1590139303292)(C:\Users\andyhkmo\AppData\Roaming\Typora\typora-user-images\1590033396599.png)]Muduo - Reactor模式_第6张图片


由于muduo整体架构one loop per thread + threadpool的架构,也可以说是一个主EventLoop和EventLoopPool的方式。

主EventLoop管理Acceptor,主要是listen和accept新的连接,然后由EventLoopPool去处理新Channel的读写事件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2s5ypFkL-1590139303293)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic8.png)]Muduo - Reactor模式_第7张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mojSBfzK-1590139303294)(C:\Users\andyhkmo\AppData\Roaming\Typora\typora-user-images\1590040905144.png)]Muduo - Reactor模式_第8张图片


待续:muduo中的线程安全日志的实现,异步日志。

你可能感兴趣的:(C++)