2016-02-29 88 views
-2

我用Tornado寫了一個簡單的http服務器,但有時候它會在下面引發異常,self.session.response在一個線程池中運行。龍捲風引發的異常

代碼服務器:

代碼 WorkerHander
class AuToServer(object): 

    module_path = os.path.split(os.path.realpath(__file__))[0] + '/../module/' 

    def __init__(self, prefix=DEFAULT_PREFIX, work_root=module_path, module=[], **kwargs): 
     self._prefix = prefix 
     self._thread_pool = ExecutorDelegate(20) 
     self._module_manager = ModuleManager(work_root) 
     self.initilize(module, kwargs) 

    def initilize(self, modules, kwargs): 

     self._module_manager.set_args(kwargs) 
     if not self._module_manager.prepare(modules): 
      print "initilize module fail. [%s]" % (str(modules)) 
      raise AppInitError("initilize %s fail" % (modules)) 

    def __call__(self, request):    # request handler 
     session = Session(request) 

     if not session.parse(self._prefix): 
      print "parse query fail. [%s]" % (session.query) 
      session.response("url parse fail [%s]\n" % session.query) 
      return 

     self._thread_pool.submit(WorkerHander(self._module_manager, session)) 

    def start(self, port=8880): 
     http_server = tornado.httpserver.HTTPServer(self, max_header_size=128*1024) 
     http_server.listen(port) 
     tornado.ioloop.IOLoop.instance().start() 

代碼
class WorkerHander(BaseExecutor): 

    def __init__(self, module_manage, session): 
     self.module_manage = module_manage 
     self.session = session 
     super(WorkerHander, self).__init__(self) 

    def run(self): 
     method = self.session.get_command() 
     if not method: 
      self.session.response("invalid url [%s]\n" % (self.session.query)) 
      return 

     context = self.module_manage.run(method, self.session) 
     try: 
      if context: 
       self.session.response(context) # raise exception 
      else: 
       self.session.response("None\n") 
     except Exception, error: 
      Logger.warning("session response fail. [%s][%s]" % (self.session.query, traceback.format_exc())) 

session.response

def response(self, context): 
    if not self.request: 
     return False 

    if isinstance(context, unicode): 
     context = context.encode("utf8") 
    self.request.write(utf8("%s %d\r\n\r\n%s" % ( 
         HTTP_HEADER, 
         len(context), 
         context))) 
    Logger.debug("QUERY:[cmd:%s][%s] [%s] [%s]" % ( 
        self.command, 
        time.time() - self.begin_time, 
        self.request.remote_ip, 
        self.query)) 

    self.request.finish() 
    return True 

例外:

2016-02-29 16:29:26,852 WARNING: server.py:run:94: session response fail. [/auto?start_timestamp=1456730772&_cmd=get_index_info][Traceback (most recent call last): 
    File "/home/admin/autobots/lib/python2.7/site-packages/autobase-0.0.1-py2.7.egg/autobase/service/server.py", line 90, in run 
    self.session.response(context) 
    File "/home/admin/autobots/lib/python2.7/site-packages/autobase-0.0.1-py2.7.egg/autobase/service/session.py", line 43, in response 
    self.request.finish() 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/httputil.py", line 407, in finish 
    self.connection.finish() 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/http1connection.py", line 459, in finish 
    self._pending_write.add_done_callback(self._finish_request) 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/concurrent.py", line 243, in add_done_callback 
    fn(self) 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/http1connection.py", line 491, in _finish_request 
    self.close() 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/http1connection.py", line 297, in close 
    self.stream.close() 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/iostream.py", line 427, in close 
    self.close_fd() 
    File "/home/admin/autobots/lib/python2.7/site-packages/tornado-4.2-py2.7-linux-x86_64.egg/tornado/iostream.py", line 995, in close_fd 
    self.socket.close() 
AttributeError: 'NoneType' object has no attribute 'close' 
] 

我是否以錯誤的方式使用龍捲風?請求幫忙。謝謝〜

+0

提供了產生該代碼的代碼。 – kwarunek

回答

2

龍捲風是not thread-safe的設計。您可以使用線程池來完成自己的工作,但必須從IOLoop線程調用所有Tornado方法(包括self.request.writeself.request.finish)。