coroutine也是一种并发模型,但不同于thread和callback,它的所有task都是可以在一个线程里面执行,然后可以通过在一个task里面主动放弃执行来切换到另一个task执行,它的调度是程序级的,不像thread是系统级的调度。gevent就是一个基于coroutine的python网络开发框架,不像twisted那样集成了很多库和协议,gevent非常精简,当然文档也很少,在性能上的话,看了PyCon上的视频,对比了twisted和其他的几个库,在内存的性能上非常地优秀,代码简洁而且也支持多核。
做了个相当简单的ChatService,有登录、群发消息、退出这3个消息,协议就是用简单的json了,有时间再试试xmpp看看。”monkey.patch_all()” 这个调用就把python原生的一些socket对象和方法替换成非阻塞的异步调用,写起来感觉还是很方便。
06 | from gevent import monkey; monkey.patch_all(); |
07 | from gevent.server import StreamServer |
08 | from common import Protocol, gen_pro_data, parse_pro_data |
14 | Protocol.Connect : self.connect, |
15 | Protocol.SendMsg : self.sendmsg, |
16 | Protocol.Quit : self.quit, |
19 | def connect(self, sock, data): |
20 | userinfo = self._clients.get(sock, None) |
22 | self._clients[sock] = data['name'] |
23 | print "New User : %s" % (data['name'],) |
25 | def sendmsg(self, sock, data): |
26 | msg = gen_pro_data(data) |
27 | for s, u in self._clients.items(): |
31 | def quit(self, sock, data=None): |
32 | if sock in self._clients: |
33 | print "User [%s] quit." % (self._clients[sock],) |
34 | del self._clients[sock] |
37 | def process(self, sock, promsg): |
39 | func = self._handlers[cmd] |
43 | chatservice = ChatService() |
48 | length = ord(sock.recv(1)) |
49 | content = sock.recv(length) |
50 | # protocol : length + json({'cmd' : 'sendmsg', 'msg' : 'hallo'}) |
51 | promsg = parse_pro_data(content) |
52 | chatservice.process(sock, promsg) |
54 | chatservice.quit(sock) |
57 | if __name__ == "__main__": |
59 | port = int(sys.argv[2]) |
60 | print "Start chat server on %s:%s" % (host, port) |
62 | chatserver = StreamServer((host, port), serve) |
63 | chatserver.serve_forever() |
写了一个简单的测试,创建了5000个连接,然后定时发消息,服务器也没显得有什么压力。
03 | from gevent.pool import Pool |
05 | def robot(idx, host, port): |
07 | chatservice = ChatService(host, port) |
08 | chatservice.connect("user%s" % (idx,)) |
10 | chatservice.sendmsg("hallo from %s" % (idx,)) |
13 | port = int(sys.argv[2]) |
16 | for i in range(count): |
17 | pool.spawn(robot, i, host, port) |