线程BaseHTTPServer,每个请求一个线程

时间:2013-10-23 08:52:38

标签: python multithreading

我正在尝试使用BaseHttpServerThreadingMixIn创建一个多线程Web服务器(如各种示例所示)。伪代码就像:

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
             pass
    def do_POST(self):
             pass

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

if __name__ == '__main__':
    server = ThreadedHTTPServer(('localhost', 9999), Handler)
    print 'Starting server, use <Ctrl-C> to stop'
    server.serve_forever()

这可以按预期工作,但我的问题是并非每个请求都获得一个线程,但是每个URL都进行了线程化。我已经测试了它:我有一个URL绑定执行以下方法:

import time
import datetime

def request_with_pause(self):
    print datetime.datetime.now().strftime("%H:%M:%S.%f"), 'REQUEST RECEIVED'
    time.sleep(10)
    print datetime.datetime.now().strftime("%H:%M:%S.%f"), 'SENT RESPONSE'

它工作正常,除非我在暂停5秒时调用网址两次(点击网址,等待5秒再点击一次) - 两个“响应”在10秒后到达(第一次点击的响应。)

1 个答案:

答案 0 :(得分:6)

在Python 2.7中:

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from threading import Thread

class ThreadedHTTPServer(HTTPServer):
    def process_request(self, request, client_address):
        thread = Thread(target=self.__new_request, args=(self.RequestHandlerClass, request, client_address, self))
        thread.start()
    def __new_request(self, handlerClass, request, address, server):
        handlerClass(request, address, server)
        self.shutdown_request(request)

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write("hello world")

server = ThreadedHTTPServer(('', 80), Handler)
#server.serve_forever()

您可以在 SocketServer.py 中找到 HTTPServer 类的主要源代码,您可以在Python的 Lib 文件夹中找到该代码。目录。 ( HTTPServer 继承自 TCPServer TCPServer 继承自 BaseServer 。)

重要的一行是315:

def process_request(self, request, client_address):
    self.finish_request(request, client_address)
    self.shutdown_request(request)

def finish_request(self, request, client_address):
    self.RequestHandlerClass(request, client_address, self)

此时,服务器使用您的Handler类创建新的请求对象。 BaseRequestHandler 构造函数自动调用self.setup(),self.handle()和self.finish()方法。

所以我做的是覆盖process_request方法,将这些东西移到一个新的线程中。