Python HTTP服务器与多线程

2 投票
4 回答
9138 浏览
提问于 2025-04-17 22:25

我尝试用Python和线程来创建一个HTTP服务器:

from socketserver import ThreadingMixIn
from http.server import HTTPServer, BaseHTTPRequestHandler
import time, threading

class ThreadingServer(ThreadingMixIn, HTTPServer):
    pass
class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        print("do")
        time.sleep(10)
        message =  threading.currentThread().getName()
        self.wfile.write(message)
        self.wfile.write('\n')

if __name__ == "__main__":
    httpd = ThreadingServer( (host, port), Handler)
    httpd.serve_forever()

这个服务器运行得不错,但如果有两个请求同时到达,它们会一个接一个地执行。也就是说,第二个请求要等第一个请求完成后才能执行。

4 个回答

0

我遇到了同样的问题,发现了一个比较旧的问题。结果发现,对我来说,问题出在我使用了谷歌浏览器。这个浏览器似乎会把对同一个网址的请求排队处理。所以第二个请求在第一个请求的响应还没回来之前是不会发送的,这样就让人觉得服务器是一个一个地处理请求。用 curl -i <你的网址在这里> 就好用多了。

0

Python的设计中有一个叫做全局解释器锁(GIL)的东西,它的作用是确保在任何时候只运行一条Python指令。这就意味着Python不能同时运行多段代码,这也就是为什么你的代码是一个接一个地执行的原因。你可以在这里了解更多关于GIL的信息。

如果你想绕过GIL,有一个选项可以选择:可以看看multiprocessing这个包。

0

你的代码在Python中写得很适合多线程。我看不出有什么理由让它变成顺序执行。你可以试试随机的休眠时间。

顺便说一下:Python中的线程和操作系统的线程不一样。普通的Python脚本是在一个单进程、单线程的虚拟机中运行的,因此在任何时候只能有一个Python线程在运行。(如果你想了解更多,可以查一下GIL)

你可以试试使用PyPy来实现真正的多线程。

1

你说得完全正确:ThreadingMixIn 会让你的整个处理程序变得顺序执行,也就是说它一次只能处理一个请求。

相反,你需要的是这样的东西:

import time, socket, threading

sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 8000

sock.bind((host, port))
sock.listen(1)

HTTP = "HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\n\n"

class Listener(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True # stop Python from biting ctrl-C
        self.start()

    def run(self):
        conn, addr = sock.accept()
        conn.send(HTTP)

        # serve up an infinite stream
        i = 0
        while True:
            conn.send("%i " % i)
            time.sleep(0.1)
            i += 1

[Listener() for i in range(100)]
time.sleep(9e9)

你甚至可以使用上面的方法,而不需要自己写一个HTTP服务器:

Python 2.7:支持在一个端口上处理多个连接的流式HTTP服务器

撰写回答