华子的代码空间

逆水行舟,不进则退。 关注系统编程、网络编程、并发、分布式。

tornado长连接断开的处理机制

使用tornado的异步http调用时候,在继续RequestHandler的子类中,可以重载on_connection_close方法。

此方法在对端连接关闭,或者在socket上读写错误的时候被调用,可以让服务器做一些清理。

 

调用过程大概这样:

首先说明,ioloop没有保证读写出错的时候做什么,以及怎么做。

这些都是由iostream来操作的,因为它就是对ioloop的封装,增加了错误处理、各种情况下的回调、读写缓存等等。

1. on_connection_close虽然是在web.py中定义的,但是其实它是由iostream来调用,tcp_server/http_server都是继承了此方法。

2. iostream调用on_connectioin_close这个回调函数的是self.close()函数

3. 在以下函数中调用了self.close方法:
(1). 在iostream的_handle_events函数中(这个函数由ioloop调用)
(2). 在_run_callback中,当执行回调失败时调用。说明当服务端代码出错时,执行self.close.
(3). 在_handle_read中调用,这个没啥悬念
(4). 在read_from_fd中调用,这里其实就是直接从socket读数据
(5). 在_handle_write中调用,同样没什么悬念
(6). 在read_from_fd中调用,其实上面的_handle_read最终调用的还是read_from_fd
(7). 在connect中调用,对于使用iostream作为client连接,也会调用

4. 接下来看看self.close的代码:

 1 def close(self, exc_info=False):
 2     """Close this stream.
 3 
 4     If ``exc_info`` is true, set the ``error`` attribute to the current
 5     exception from `sys.exc_info()` (or if ``exc_info`` is a tuple,
 6     use that instead of `sys.exc_info`).
 7     """
 8     if not self.closed():
 9         if exc_info:
10             if not isinstance(exc_info, tuple):
11                 exc_info = sys.exc_info()
12             if any(exc_info):
13                 self.error = exc_info[1]
14         if self._read_until_close:
15             callback = self._read_callback
16             self._read_callback = None
17             self._read_until_close = False
18             self._run_callback(callback,
19                                self._consume(self._read_buffer_size))
20         if self._state is not None:
21             self.io_loop.remove_handler(self.fileno())
22             self._state = None
23         self.close_fd()
24         self._closed = True
25     self._maybe_run_close_callback()

最后一句,就是self._maybe_run_close_callback(),说明如果定义了on_connection_close函数,就调用它。

在这句代码的前面做了一些例如关闭连接、清除回调、从ioloop中移除回调等等。

 

5. 总的说来,还是不复杂的,合情合理。

 

posted on 2013-03-08 20:18  华子的代码空间  阅读(3615)  评论(0编辑  收藏  举报

导航