channels之延时大法

前言

做一个任务发布模块的时候,需要延时任务的功能。本来想着是使用线程去做的,甚至是队列去做。但是思前想后觉的不太妥当。毕竟我需要的不是堵塞式的延时任务。最后大佬给指点迷津,使用channels的asgi.delay去完成延时功能。

流程如下:

  1. 下载插件:
    pip install channels
    pip install asgi_redis
  2. 在django的settings中设置参数:
    “`python
    INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders',
    'rest_framework',
    'channels', #channels
    'channels.delay', #延时
    ]</li>
    </ol>

    <pre><code class="">3. 新增参数CHANNEL_LAYERS(这个具体的参数不清楚,但是最后一个ROUTING是表示WebSocket表单的位置,当有WebSocket请求访问时,就会根据这个路径找到相应表单,调用相应的函数进行处理):
    “`python
    CHANNEL_LAYERS = {
    “default”: {
    “BACKEND”: “asgi_redis.RedisChannelLayer”,
    “CONFIG”: {
    “hosts”: [(“localhost”, 6379)],
    “prefix”: u”xxx”,
    “expiry”: 60 * 10,
    “capacity”: 8192,
    },
    “ROUTING”: “xxx.routers.routerpatterns”,
    },
    }

    1. 在xxx.routers中写上路由表:
    from channels.routing import route
    
    routerpatterns = [
        route('control', function), #function为对应的延时之后接受延时的函数
    ]
    
    1. 举例说明:
      1、调用延时的例子:
    def start_checker():
        # 这是使用延时,相当于客户端
    
        data = {
            "name": "april",
            "ages": 18,
        }
    
        timw = 0
    
        delayed_message = {
            'channel': 'control',
            'content': data,
            'delay': time*1000
        }
        Channel('asgi.delay').send(delayed_message)
    

    2、接受延时的例子:

    def function(message):
        """
        这里是接受,相当于服务端
        """
       data = message.get("content", None)
        if data:
            name = data.get("name")
            #Do something
            print name
    
    1. 记得要运行 python manage.py rundelay,这样子才能进行通信。

    注意

    在debug是,我数据库连接的是线上数据库。本地执行了 python manage.py rundelay,导致线上的延时总是接受不到,原因是本地的 python manage.py rundelay 跑着呢,
    延时的信息都存在了一个表中: channels.delay_delayedmessage,如果要删除已经发布的但是为执行的延时,删除数据库中相对应的数据就行了