V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
yueyoum
V2EX  ›  Python

uwsgi websockets + gevent 新姿势

  •  
  •   yueyoum ·
    yueyoum · 2015-08-02 23:00:05 +08:00 · 3797 次点击
    这是一个创建于 3406 天前的主题,其中的信息可能已经有所发展或是发生改变。

    uwsgi 已经merge了我的 pull request,
    现在大家可以用下面这种更加 gevent 的方式来使用 uwsgi 的 websockets 了

    class Client(object):
        def __init__(self):
            self.ctx = None
            self.send_queue = Queue()
            self.jobs = []
    
    
        def _recv_job(self):
            while True:
                data = uwsgi.websocket_recv(request_context=self.ctx)
                self.on_data(data)
    
        def _send_job(self):
            while True:
                data = self.send_queue.get()
                uwsgi.websocket_send(data, request_context=self.ctx)
    
        def _exit(self, *args):
            for j in self.jobs:
                j.unlink(self._exit)
    
            gevent.killall(self.jobs)
            ClientManager.remove(self)
            self.on_exit()
    
    
        def on_data(self, data):
            print "GOT: {0}".format(data)
            ClientManager.broadcast(data)
    
    
        def on_exit(self):
            print "bye bye..."
    
    
        def send(self, data):
            self.send_queue.put(data)
    
    
        def start(self):
            uwsgi.websocket_handshake()
            self.ctx = uwsgi.request_context()
    
            ClientManager.add(self)
    
            self.jobs.extend([
                gevent.spawn(self._recv_job),
                gevent.spawn(self._send_job),
            ])
    
            for j in self.jobs:
                j.link(self._exit)
    
            gevent.joinall(self.jobs)
    

    完整例子见:

    https://github.com/unbit/uwsgi/blob/master/tests/websockets_chat_2.py

    下一步的目标是,
    模仿erlang 的两个功能:

    1. global_register
      每个greenlet 都可以全局注册自己, 然后其他 greenlet 直接 call(ID, data) or cast(ID, data) 就可以发送消息给对应的greenlet

    2. gp2, process_group
      给 greenlet 分组用的。 给这个组发消息,这个组里面的每个greenlet 都会收到消息。

    实现方式可能是:

    1. program mule
    2. uwsgi plugin
    3. 直接修改uwsgi代码,并发pull request

    最后的目标就是 让以上功能也能用在 uwsgi 集群中, 这样一个分布式的websocket server就能很容易的实现了。并且跑在上面的python 代码,greenlets 之间的通信可以像erlang那么简单

    4 条回复    2015-08-03 10:03:49 +08:00
    likang
        1
    likang  
       2015-08-03 00:06:56 +08:00
    哇哦,大赞!
    dcoder
        2
    dcoder  
       2015-08-03 01:31:43 +08:00
    @yueyoum
    是打算用 websocket 来做游戏通信吗?
    gevent VS python3的asyncio 你怎么看?
    sprite0616
        3
    sprite0616  
       2015-08-03 08:49:42 +08:00
    自己用tornado作为websocket服务器
    yueyoum
        4
    yueyoum  
    OP
       2015-08-03 10:03:49 +08:00
    @dcoder

    asyncio 扫了一眼, 有点像 twisted, 还是把逻辑给打散了。

    个人因为对 gevent 比较熟,再加上 gevent 也支持 py3了,
    所以一直没怎么了解 asyncio
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1125 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 19:06 · PVG 03:06 · LAX 11:06 · JFK 14:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.