Channels集成到Django消息实时推送

channel架构图

InterFace Server:负责对协议进行解析,将不同的协议分发到不同的Channel

Channel Layer:频道层,可以是一个FIFO队列,通常使用Redis

 

Django中配置Channel:

CHANNEL_LAYERS的配置:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": ["redis://127.0.0.1:6379", ], 
        },
    },
}

asgi的配置:

import os
import sys
import django
from channels.routing import get_default_application


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "web.settings_local")
django.setup()
application = get_default_application()

consumers代码:

class NotificationsConsumer(AsyncWebsocketConsumer):
    """处理通知应用中的WebSocket请求"""

    async def connect(self):
        """建立连接"""
        if self.scope['user'].is_anonymous:
            # 未登录用户拒绝连接
            await self.close()
        else:
            await self.channel_layer.group_add(
                'notifications', self.channel_name
            )
            await self.accept()

    async def receive(self, text_data=None, bytes_data=None):
        """将接收到的消息返回给前端"""
        await self.send(text_data=json.dumps(text_data))

    async def disconnect(self, code):
        """断开连接"""
        await self.channel_layer.group_discard(
            'notifications', self.channel_name
        )

 channels将同步的MySQL转换为异步的:

# ORM语句同步变异步,方式一
from channels.db import database_sync_to_async
user = await database_sync_to_async(User.objects.get(username=username))

# ORM语句同步变异步,方式二
@database_sync_to_async
def get_username(username):
    return User.objects.get(username=username)

配置routing:

from django.urls import path
from channels.auth import AuthMiddlewareStack  # channels的认证中间件
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator

from notifications.consumers import NotificationsConsumer


application = ProtocolTypeRouter({
    'websocket': AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter([
                path('ws/notifications/', NotificationsConsumer),
            ])
        )
    )
})

settings中配置:

INSTALLED_APPS中加入:

'channels',

配置ASGI_APPLICATION:
ASGI_APPLICATION = 'web.routing.application'

 

notifications 业务层实现逻辑:

channel_layer = get_channel_layer()
payload = {
    'type': 'receive',
    'key': key,
    'actor_name': actor.username,
    'id_value': id_value
}
async_to_sync(channel_layer.group_send)('notifications', payload)

消息通知业务流程:
用户触发了消息 --> Django的view层 --> 保存到MySQL数据库 --> 将消息通知发送到channel对应的group里面 --> websocket将消息通过consumer推送给接收方

posted @ 2020-05-28 19:32  HarvardFly  阅读(2147)  评论(0编辑  收藏  举报