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. 总的说来,还是不复杂的,合情合理。