Skip to main content
 首页 » 编程设计

python之如何在 Python WSGI 服务器中实现多线程

2024年11月01日33kevingrace

事先澄清一下,这只是一个学习项目,我无意在生产中使用它。已经有几个非常好的 Python 应用程序服务器。但我想学习更多关于并发的知识,所以我着手写一个(我认为)我知道的东西。

此外,因为我想“更接近金属”,所以我开始只使用 Socket 并希望保持这种状态。

以下是我目前所拥有的重要部分。 self.iq 是一个队列对象 (inbound_queue),它什么都不做,只是将请求(包括套接字对象)放入 outbound_queue,然后 Consumer 对象从 outbound_queue 获取请求并将其传递给 ResponseHandler。这似乎只需要我点击它就可以正常工作,但我担心我会通过天真的实现让自己陷入竞争状态。专门将事物分配给特定于请求的 ServerClass 对象。

所以问题是:是否有更好的方法来执行此操作,或者我的队列使用是否会阻止两个线程获取并操作同一对象?我是否应该将 WSGI 环境之类的东西封装到一个单独的对象中,该对象也可以传递到队列中?由于需要传入回调函数,因此在尝试编写符合 WSGI 标准的服务器时,做这样的事情会很棘手。

class Consumer(threading.Thread): 
 
    def __init__(self, out_queue, server): 
        threading.Thread.__init__(self) 
        self.out_queue = out_queue 
        self.server = server 
 
    def run(self): 
        while True: 
        item = self.out_queue.get() 
        self.server.ResponseHandler(self.server, item) 
        self.out_queue.task_done() 
 
class QueueConsumerServer(object): 
 
    methods_allowed = ['get', 'post', 'put', 'patch', 'delete', 'options', 'upgrade'] 
 
    def __init__(self, host, port, application): 
        self.host = host 
        self.port = port 
        self.application = application 
        self.iq = Queue.Queue() 
        self.oq = Queue.Queue() 
 
        self.socket = socket.socket() 
        self.socket.bind((self.host, self.port)) 
        #<snip of lots of assigning stuff to environ> 
        self.environ = environ 
        headers_set = [] 
        headers_sent = [] 
        for i in xrange(3): 
            thr = Producer(self.iq, self.oq) 
            thr.daemon = True 
            thr.start() 
 
        for i in xrange(3): 
            thr = Consumer(self.oq, self) 
            thr.daemon = True 
            thr.start() 
 
 
    def handle_request(self): 
        self.socket.listen(1) 
        try: 
            while True: 
                cli, addr = self.socket.accept() 
                data = cli.recv(1024) 
                request_data = self.parse_request_data(data) 
                req.path = request_data[1] 
                req.cli = cli 
                self.iq.put(req) 
                return 
        except Exception, ex: 
            print 'e', ex, 
            sys.exit(1) 
        finally: 
            sys.stdout.flush() 
            self.socket.close() 

请您参考如下方法:

Python 队列是 thread safe ,因此您编写的代码中没有竞争。

关于解决此问题的更好方法,您的代码可能会达到 GIL不久。我建议调查 multiprocessing .