11

HTTPServerとThreadingMixInから継承するクラスを作成することにより、スレッド化された(Pythonスレッドを使用した)HTTPサーバーをセットアップしました。

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

BaseHTTPRequestHandlerから継承するハンドラークラスがあり、次のようなものでサーバーを起動します。

class MyHandler(BaseHTTPRequestHandler):
    ...

server = ThreadedHTTPServer(('localhost', 8080), MyHandler)
# Prevent issues with socket reuse
server.allow_reuse_address = True
# Start the server
server.serve_forever()

これはすべて非常に簡単です。私が遭遇している問題は、ThreadingMixIn、ForkingMixIn、またはそれ以外の場合、リクエストがリクエストハンドラでブロックされて戻ることです。これは、次のサンプルコードを実装することで簡単に確認できます。

class MyHandler(BaseHTTPRequestHandler):
    def respond(self, status_code):
        self.send_response(status_code)
        self.end_headers()

    def do_GET(self):
         print "Entered GET request handler"
         time.sleep(10)
         print "Sending response!"
         respond(200)

サーバーがこれらを同時に処理している場合、2つの要求を送信し、サーバーが両方のGET要求ハンドラーに入ってからいずれかの応答を送信することを確認できます。代わりに、サーバーは最初のリクエストに対してGETリクエストハンドラーに入り、それが返されるのを待ってから、2番目のリクエストを入力します(したがって、2番目のリクエストが返されるまでに10秒ではなく約20秒かかります)。

サーバーがハンドラーが戻るのを待たないシステムを実装する簡単な方法はありますか?具体的には、いくつかのリクエストを受信するのを待ってからそれらのいずれかを返す(長いポーリングの形式)システムを作成しようとしています。最初のリクエストの待機により、今後のリクエストがサーバーに接続できなくなるという問題が発生します。

4

1 に答える 1

15
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

十分です。クライアントはおそらく同時リクエストを行いません。リクエストを並行して行うと、スレッドサーバーは期待どおりに機能します。クライアントは次のとおりです。

#!/usr/bin/env python
import sys
import urllib2

from threading import Thread

def make_request(url):
    print urllib2.urlopen(url).read()

def main():
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000
    for _ in range(10):
        Thread(target=make_request, args=("http://localhost:%d" % port,)).start()

main()

そして対応するサーバー:

import time
from BaseHTTPServer   import BaseHTTPRequestHandler, HTTPServer, test as _test
from SocketServer     import ThreadingMixIn


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

class SlowHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()

        self.wfile.write("Entered GET request handler")
        time.sleep(1)
        self.wfile.write("Sending response!")

def test(HandlerClass = SlowHandler,
         ServerClass = ThreadedHTTPServer):
    _test(HandlerClass, ServerClass)


if __name__ == '__main__':
    test()

10件のリクエストはすべて1秒で終了します。サーバー定義から削除するThreadingMixInと、10個のリクエストすべてが完了するまでに10秒かかります。

于 2012-09-29T08:47:53.007 に答える