【问题标题】:Python HTTP-Server and ThreadingPython HTTP 服务器和线程
【发布时间】:2014-04-20 16:23:08
【问题描述】:

我尝试使用线程在 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()

服务器运行良好,但如果两个请求是同一时间,它们是按顺序执行的。 所以第二个请求在第一个请求完成之前不会执行。

【问题讨论】:

  • 当您说“它们是按顺序执行的”时:如果您发送两个请求(一个接一个地很快),两个请求都需要大约 20 秒才能返回吗?
  • 问题是ThreadingMixIn 正在对您的处理程序进行排序。不幸的是,版主删除了我的答案,即使您的问题不是完全重复的。我会尝试再次发布。

标签: python multithreading basehttpserver


【解决方案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: streaming HTTP server supporting multiple connections on one port

【讨论】:

  • 这是ThreadingMixin 使处理程序顺序的关键信息。您可以添加一些参考信息吗?令我惊讶的是,这个核心课程会如此步履蹒跚。它解释了我在 python Web 服务器上的很多问题。
  • @javadba。我(当然还有其他人)花了一些时间试图理解ThreadingMixIn...但是,在软件中,在某些时候,您需要知道原始作者的想法,并且他们没有记录 HTTP 流应用程序。 .. 对我来说,SocketServer 的某些功能似乎过于抽象,因此需要进行太多工作才能正确设置。 IMO 我们已经在这方面花费了足够多的时间,并且有效地,目前的答案是将BaseHTTPServer 包装在您自己的线程启动器中,就像我suggested 一样。
【解决方案2】:

您的代码非常适合 python 中的多线程。我看不出为什么这是连续的。您可能想尝试随机睡眠间隔。

顺便说一句:Python 线程与 OS 线程不同。一个普通的 Python 脚本在单进程、单线程的 VM 中运行,因此任何时候都只能运行一个 Python 线程。 (如果您想了解更多信息:查找 GIL)

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

【讨论】:

  • 感谢您的回答!但是没有其他方法可以在 Python 中创建一个能够同时响应多个请求的网络服务器。按照我在示例中使用的方式,每个 Handler-Object 都在一个新线程中运行。我希望当它们在两个线程中运行时,它们可以同时执行。 (我希望你听不懂我的英语:|)
  • 您的代码对于在python中的多线程来说似乎很好,而且应该是这样做的;我确实认为这表现出顺序行为是有问题的。
【解决方案3】:

Python 是围绕一种称为全局解释器锁 (GIL) 的结构设计的,它确保在任何给定时间只运行一条 Python 指令。这意味着 Python 不能并行运行代码,这就解释了为什么你的代码是串行运行的。您可以阅读有关 GIL 的更多信息here

如果您想避开 GIL,那么您可以选择:查看 multiprocessing 包。

【讨论】:

  • 仅仅因为python是单处理的并不意味着它不能有多个异步线程。阻塞 I/O 调用将导致 python 切换线程。 OP 知道这一点,并且为此使用线程是正确的。
【解决方案4】:

我遇到了同样的问题,发现了这个老问题。原来对我来说问题是我使用的是谷歌浏览器,它似乎将请求序列化到同一个 URL。因此,在第一个请求得到响应之前,第二个请求不会发送,因此服务器似乎正在按顺序处理请求。使用curl -i <your URL here> 效果更好。

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多