defhandler_request(self,request):answ=self.remote_server.query(request)# this takes 5 secondsrequest.write_response(answ)
并发性低,当然可以采用多线程(多进程)处理,但是开销也较大。
但是采用异步接口,类似如下代码
123456789
defhandler_request(self,request):self.remote_server.query_async(request,self.response_received)defresponse_received(self,request,answ):# this is called 5 seconds laterrequest.write(answ)
可以参考pythond的异步网络框架twisted
源码和安装
可以利用easy_install或者pip进行安装
1
$sudo easy_install tornado
或者下载后安装
123
git clone http://github.com/facebook/tornado.git
cd tornado
sudo python setup.py install
defadd_handler(self,fd,handler,events):"""Registers the given handler to receive the given events for fd."""self._handlers[fd]=handlerself._impl.register(fd,events|self.ERROR)
defstart(self):"""Starts the I/O loop. The loop will run until one of the I/O handlers calls stop(), which will make the loop stop after the current event iteration completes. """self._running=TruewhileTrue:[...]ifnotself._running:break[...]try:event_pairs=self._impl.poll(poll_timeout)exceptException,e:ife.args==(4,"Interrupted system call"):logging.warning("Interrupted system call",exc_info=1)continueelse:raise# Pop one fd at a time from the set of pending fds and run# its handler. Since that handler may perform actions on# other file descriptors, there may be reentrant calls to# this IOLoop that update self._eventsself._events.update(event_pairs)whileself._events:fd,events=self._events.popitem()try:self._handlers[fd](fd,events)exceptKeyboardInterrupt:raiseexceptOSError,e:ife[0]==errno.EPIPE:# Happens when the client closes the connectionpasselse:logging.error("Exception in I/O handler for fd %d",fd,exc_info=True)except:logging.error("Exception in I/O handler for fd %d",fd,exc_info=True)
def__init__(self,impl=None):[...]# Create a pipe that we send bogus data to when we want to wake# the I/O loop when it is idler,w=os.pipe()self._set_nonblocking(r)self._set_nonblocking(w)self._waker_reader=os.fdopen(r,"r",0)self._waker_writer=os.fdopen(w,"w",0)self.add_handler(r,self._read_waker,self.WRITE)def_wake(self):try:self._waker_writer.write("x")exceptIOError:pass
定时器
对于IOLoop模块来说实现一个定时器非常简单,利用python的bisect模块实现如下
123456789
defadd_timeout(self,deadline,callback):"""Calls the given callback at the time deadline from the I/O loop."""timeout=_Timeout(deadline,callback)bisect.insort(self._timeouts,timeout)returntimeout
def_handle_events(self,fd,events):whileTrue:try:connection,address=self._socket.accept()exceptsocket.error,e:ife[0]in(errno.EWOULDBLOCK,errno.EAGAIN):returnraisetry:stream=iostream.IOStream(connection,io_loop=self.io_loop)HTTPConnection(stream,address,self.request_callback,self.no_keep_alive,self.xheaders)except:logging.error("Error in connection callback",exc_info=True)