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
vimiix
V2EX  ›  Python

求助:关于 Channels2.0 的使用问题

  •  
  •   vimiix ·
    vimiix · 2018-07-23 16:27:04 +08:00 · 2970 次点击
    这是一个创建于 2309 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题背景:

    我需要在后台订阅 redis 的消息,一有消息就给前端推信息。所以我这么做了:

        async def connect(self):
            logger.info("websocket connected.")
            redis_conn = StrictRedis(**settings.REDIS_DB)
            self.ps = redis_conn.pubsub()
            await self.ps.subscribe(settings.REDIS_CHANNELS)
    
            await self.accept()
    
        async def disconnect(self, code):
            logger.info("websocket disconnected.")
            await self.ps.unsubscribe()
            await self.close()
    
        async def receive(self, text_data=None, bytes_data=None):
            logger.info("websocket received data.\n%s" % text_data)
            try:
                data = json.loads(text_data)
                self.user_id = data['payload'].get('user_id')
            except json.JSONDecodeError:
                await self.close()
    
            while True:
                # 获取 redis 的消息
                msg = await self.get_msg_from_queue()
                if not msg:
                    continue
                logger.info("get msg %s" % msg)
                await self.send(text_data=json.dumps(msg))
    

    打开前端页面的时候,链接成功 websocket 会立马发一个信息,来对接,后端确认以后开始等 redis 的消息,这里我使用的 while 循环,就是因为这个 while 循环,导致我前端断开 websocket 链接以后,后端不会触发 disconnect()函数,所有就没有关闭这个实例,导致后端不断报这个错误:

    WARNING  Application instance <Task pending coro=<AsyncConsumer.__call__() 
    running at /xxx/venv/lib/python3.6/site-packages/channels/consumer.py:54> 
    wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fade64e0678>()]>> 
    for connection <WebSocketProtocol client=['127.0.0.1', 49204] path=b'/listen'> 
    took too long to shut down and was killed.
    

    求助 V 站大佬,我该如何在 while 循环中来判断当前客户端是否断开呢?

    3 条回复    2018-07-23 18:55:25 +08:00
    myyou
        1
    myyou  
       2018-07-23 18:22:14 +08:00
    如果你用的是 channels-redis,看看源码,等待消息的逻辑已经实现了,你不用重复搞一遍。
    你这样搞等于把接受消息端的给阻塞了。
    virusdefender
        2
    virusdefender  
       2018-07-23 18:46:16 +08:00
    不要在 receive 中阻塞,而是在一个单独的进程中 pull 消息,然后推送给响应的 client

    http://channels.readthedocs.io/en/latest/introduction.html#cross-process-communication
    vimiix
        3
    vimiix  
    OP
       2018-07-23 18:55:25 +08:00
    @myyou 好的,谢谢指点。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2883 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:47 · PVG 22:47 · LAX 06:47 · JFK 09:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.