【问题标题】:Python BaseHTTPServer and TornadoPython BaseHTTPServer 和 Tornado
【发布时间】:2013-06-09 18:29:57
【问题描述】:

我正在运行一个 BaseHTTPServer,通过 ThreadedHTTPServer 传递,所以我得到了线程。

server = ThreadedHTTPServer(('', int(port)), MainHandler)

接下来我根据这里的信息分叉:Daemonizing python's BaseHTTPServer

然后我做:

server.serve_forever()

我想要做的是让相同的 Python 脚本也运行 Tornado WebSocket 服务器,我尝试创建第二个处理程序并在我的主要创建类似于上面的第二个服务器,但是随后 serve_forever() 块(我假设)并且我无法启动 Tornado WebSocket 服务器。

我也曾考虑使用 Tornado 来服务于我的一般 Web 内容,但性能非常糟糕且无法使用,因此我更愿意同时运行它,除非有更简单的替代方法可以将 WebSockets 添加到 BaseHTTPServer。

谁能提供解决方案?

【问题讨论】:

  • “性能太棒了,无法使用”?它应该非常接近;你是怎么测试的?无论如何,nginx 应该是为您的“一般网络内容”提供服务的最快方式。
  • 我尝试提供一个简单的静态 html 页面,但加载需要几秒钟。我想,回想起来,这是我的错误设置,而不是 Tornado 的错。

标签: python-2.7 websocket tornado basehttpserver basehttprequesthandler


【解决方案1】:

是的,serve_forever() 阻止了这一切。您可以使用handle_request 一次处理一个请求。为确保它不会阻塞,您必须设置超时。要定期运行它,您可以使用tornado.ioloop.PeriodicCallback。示例:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading

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

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class Handler(BaseHTTPRequestHandler):  
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        message =  threading.currentThread().getName()
        self.wfile.write(message)
        self.wfile.write('\n')
        return

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!\n')

if __name__ == '__main__':
    # create Tornado Server
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)

    # create BaseHTTPServer
    server = ThreadedHTTPServer(('localhost', 8080), Handler)
    server.timeout = 0.01 

    tornado.ioloop.PeriodicCallback(server.handle_request, 100).start() # every 100 milliseconds
    tornado.ioloop.IOLoop.instance().start()

跑步:

$ curl http://localhost:8080/
Thread-1
$ curl http://localhost:8080/
Thread-2
$ curl http://localhost:8000/
Hello, friendly user!
$ curl http://localhost:8080/
Thread-3
$ curl http://localhost:8000/
Hello, friendly user!
$ curl http://localhost:8080/
Thread-4
$ curl http://localhost:8000/
Hello, friendly user!
$ curl http://localhost:8000/
Hello, friendly user!

我在这里使用timeout 属性来设置超时。我不确定这是否是正确的方法。其他方法:http://code.activestate.com/recipes/499376/

另一种解决方案:在自己的线程中运行每个服务器:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading

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

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class Handler(BaseHTTPRequestHandler):  
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        message =  threading.currentThread().getName()
        self.wfile.write(message)
        self.wfile.write('\n')
        return

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!\n')

def run_tornado():
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

def run_base_http_server():
    server = ThreadedHTTPServer(('localhost', 8080), Handler)
    server.serve_forever()

if __name__ == '__main__':
    threading.Thread(target=run_tornado).start()
    threading.Thread(target=run_base_http_server).start()

【讨论】:

  • 哇,感谢您提供非常详细的回复,并为我提供了选择。我会同时运行它们,看看哪个效果最好,但肯定会接受这个答案。
猜你喜欢
  • 2012-02-06
  • 2013-04-07
  • 2015-05-02
  • 2012-09-05
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多