只是为了澄清这只是一个学习项目,我无意在生产中使用它。已经有几个非常好的Python应用程序服务器。但我想了解更多关于并发的知识,所以我开始写一些(我认为)我知道的事情。
另外,因为我想“更接近金属”,所以我开始只使用Socket,并希望保持这种方式。
以下是我到目前为止的重要部分。 self.iq是一个Queue对象(inbound_queue),它实际上什么都不做,但将请求(包括套接字对象)放入outbound_queue,然后Consumer对象从outbound_queue获取请求并将其传递给ResponseHandler。这似乎很好,只是我打它但我担心我打开自己达到一个天真实施的竞争条件。专门为ServerClass对象分配特定于请求的内容。
所以问题是:有没有更好的方法来做到这一点,或者我的Queue使用是否阻止两个线程在同一个对象上拾取和操作?我是否应该将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()
答案 0 :(得分:2)
Python队列是thread safe,因此您的代码中没有写入的比赛。
关于更好的方法来解决这个问题,您的代码可能会在很长时间内达到GIL。我建议进入multiprocessing。