Chinaunix首页 | 论坛 | 博客
  • 博客访问: 534762
  • 博文数量: 142
  • 博客积分: 2966
  • 博客等级: 少校
  • 技术积分: 1477
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-07 22:37
文章分类

全部博文(142)

文章存档

2013年(3)

2012年(21)

2011年(53)

2010年(33)

2009年(32)

分类: Python/Ruby

2011-11-26 00:50:42

基于coroutine的gevent

without comments

coroutine也是一种并发模型,但不同于thread和callback,它的所有task都是可以在一个线程里面执行,然后可以通过在一个task里面主动放弃执行来切换到另一个task执行,它的调度是程序级的,不像thread是系统级的调度。gevent就是一个基于coroutine的python网络开发框架,不像twisted那样集成了很多库和协议,gevent非常精简,当然文档也很少,在性能上的话,看了PyCon上的视频,对比了twisted和其他的几个库,在内存的性能上非常地优秀,代码简洁而且也支持多核。

做了个相当简单的ChatService,有登录、群发消息、退出这3个消息,协议就是用简单的json了,有时间再试试xmpp看看。”monkey.patch_all()” 这个调用就把python原生的一些socket对象和方法替换成非阻塞的异步调用,写起来感觉还是很方便。

01#!/usr/bin/env python
02#-*- coding:utf-8 -*-
03 
04import sys
05import simplejson
06from gevent import monkey; monkey.patch_all();
07from gevent.server import StreamServer
08from common import Protocol, gen_pro_data, parse_pro_data
09 
10class ChatService:
11    def __init__(self):
12        self._clients = {}
13        self._handlers = {
14            Protocol.Connect : self.connect,
15            Protocol.SendMsg : self.sendmsg,
16            Protocol.Quit : self.quit,
17        }
18 
19    def connect(self, sock, data):
20        userinfo = self._clients.get(sock, None)
21        if userinfo: return
22        self._clients[sock] = data['name']
23        print "New User : %s" % (data['name'],)
24 
25    def sendmsg(self, sock, data):
26        msg = gen_pro_data(data)
27        for s, u in self._clients.items():
28            if sock != s:
29                s.send(msg)
30 
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]
35            sock.close()
36 
37    def process(self, sock, promsg):
38        cmd = promsg['cmd']
39        func = self._handlers[cmd]
40        func(sock, promsg)
41 
42# server chat service
43chatservice = ChatService()
44 
45def serve(sock, addr):
46    while True:
47        try:
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)
53        except:
54            chatservice.quit(sock)
55            break
56 
57if __name__ == "__main__":
58    host = sys.argv[1]
59    port = int(sys.argv[2])
60    print "Start chat server on %s:%s" % (host, port)
61    try:
62        chatserver = StreamServer((host, port), serve)
63        chatserver.serve_forever()
64    except:
65        chatserver.kill()

写了一个简单的测试,创建了5000个连接,然后定时发消息,服务器也没显得有什么压力。

01def test():
02    import gevent
03    from gevent.pool import Pool
04 
05    def robot(idx, host, port):
06        # client chat service
07        chatservice = ChatService(host, port)
08        chatservice.connect("user%s" % (idx,))
09        while True:
10            chatservice.sendmsg("hallo from %s" % (idx,))
11            gevent.sleep(3)
12    host = sys.argv[1]
13    port = int(sys.argv[2])
14    count = 5000
15    pool = Pool(5000)
16    for i in range(count):
17        pool.spawn(robot, i, host, port)
18    pool.join()
阅读(1750) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~