2014-03-25 41 views
5

我已阅读过有关如何运行N个Tornado进程的各种文章和教程,其中N =核心数。我的代码正在运行,运行在所有16个内核上,但我以某种方式设法搞砸了,我需要新鲜的眼睛。运行多个龙卷风进程

import tornado.ioloop 
import tornado.web 
import tornado.httpserver 

from core import settings 
from core import coreService 
import services 

from tornado.options import define, options, parse_command_line 

define("port", default=settings.SERVER_PORT, help="run on the given port", type=int) 



app = tornado.web.Application([ 
    (r'/upload', coreService.Upload) 
]) 

if __name__ == "__main__": 
    tornado.options.parse_command_line() 
    server = tornado.httpserver.HTTPServer(app, max_buffer_size=1024*1024*201) 
    server.bind(options.port) 
    # autodetect cpu cores and fork one process per core 
    server.start(0) 
    try:   
     print 'running on port %s' % options.port 
     tornado.ioloop.IOLoop.instance().start() 

    except KeyboardInterrupt: 
     tornado.ioloop.IOLoop.instance().stop() 

此代码引发此错误:

File "/opt/tornado/tornado/process.py", line 112, in fork_processes 
    raise RuntimeError("Cannot run in multiple processes: IOLoop instance " 
RuntimeError: Cannot run in multiple processes: IOLoop instance has already been initialized. You cannot call IOLoop.instance() before calling start_processes() 

我只是没有看到它。谢谢

:编辑:

正如本说,我的方法之一是给我找麻烦。这是一个方法的代码,有人可能会受益于这样的:

from tornado import gen 
import motor 

db = motor.MotorClient().open_sync().proba 
class Upload(BaseHandler): 
    @gen.engine 
    def post(self): 
     fs = yield motor.Op(motor.MotorGridFS(db).open) 

     gridin = yield motor.Op(fs.new_file) 
     yield motor.Op(gridin.write, 'First part\n') 
     yield motor.Op(gridin.write, 'Second part') 
     yield motor.Op(gridin.close) 

     print gridin._id 
     self.write(str(gridin._id)) 
     self.finish() 

EDIT 2

我已经找到了最终解决我的问题。正如Ben指出的那样,上面的方法给了我麻烦。电机文档中记录了将Tornado应用程序包含在内的正确方法。这里是一个除了这是为我工作:

if __name__ == "__main__": 
    tornado.options.parse_command_line()   
    try: 
     server = tornado.httpserver.HTTPServer(app, max_buffer_size=1024*1024*201) 
     server.bind(8888) 
     server.start(0) # autodetect cpu cores and fork one process per core 
     db = motor.MotorClient().open_sync().proba 
     print 'running on port %s' % options.port 
     # Delayed initialization of settings 
     app.settings['db'] = db # from this point on db is available as self.settings['db'] 
     tornado.ioloop.IOLoop.instance().start() 

    except KeyboardInterrupt: 
     tornado.ioloop.IOLoop.instance().stop() 
+1

对选择的版本控制系统中的工作版本使用diff函数应该告诉你什么事情发生了变化。 – XTL

回答

6

它的工作原理,如果我注释掉“核心”和“服务”的进口如预期。其中一个模块中的某些内容必须初始化单例事件循环(可能间接地,例如通过创建全局AsyncHTTPClient实例)。此警告正在保护您免受在父进程中创建的这些对象在子级中无效的事实。你必须找到创建这些对象的地方(遗憾的是没有好的工具),并将它们移到fork后面,以便它们在子进程中创建。

+0

你也可以看看这个请:http://stackoverflow.com/questions/32521122/cannot-run-in-multiple-processes-ioloop-instance-has-already-been-初始化 – moaglee

14

这个异常引发tornado.web.Application调试模式。

application = tornado.web.Application([ 
    (r"/", hello), 
], 
debug=False) 

将调试设置为False来解决此问题。

可以启动多个processe倾听每个端口:

server = tornado.httpserver.HTTPServer(application) 
server.bind(1234) # port 
server.start(4) 
tornado.ioloop.IOLoop.instance().start() 
+0

这解决了我的问题。非常不直观。谢谢。 –

+1

谢谢,这可能是最常见的问题。 –

+0

谢谢,这个答案帮助我。 –

0

我很痛苦同样的问题,甚至还成立debug=Falseautoreload=False

我的犯罪嫌疑人集中在MotorClient,创建于TornadoApp.__init__()

实例评论motor_client = ...行解决了我的问题。

class MainApp(tornado.web.Application): 
    def __init__(self): 
     handlers = [ 
      (r"/", views.HomeHandler), 
      (r".*", views.NotFoundHandler), 

     ] 

     motor_client = motor.motor_tornado.MotorClient('mongodb://localhost:27017') 

不幸的是,使用MotorClient迫使我放弃的多进程运行龙卷风。