由于公司需要开发一个监控系统,前后端方案使用 Angular+Django进行开发,协议:Websocket

由于开发时Django + Weboscket配置时找到的文档多数较老,或者大多数复制粘贴,很多代码前后不对应,所以开贴记录一下。ps:第一次发帖,结构有不完善或者有问题的可以随时指出,看到就会回复了,问题会持续更新

1.Python + Django Websocket配置

Django项目安装及新建就不演示了(项目名称:my-project),文档比较多而且简单。正文开始配置Django Websocket

项目中使用到的库及版本号:

后端:

  1. Django==3.2.3 # 2.1.14升级上来的,最后没影响
  2. Channels==3.0.3
  3. channels-redis==3.2.0

服务器端:

  1. redis:6.2.1

1.安装依赖

  1. 安装Channels
    pip install channels==3.0.3
    pip install channels-redis==3.2.0

     

  2. 服务器docker安装配置Redis,并启动容器,映射端口:6379
    docker pull redis:6.2.1
    docker run -itd --name my-redis -p 6379:6379 redis

    或者使用Rancher及K8s配置(推荐)

2.Django配置

  1. 配置 settings.py
    1. 注册channels
      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'channels', # 注册channels
      ]
    2. 配置channels layer
      ASGI_APPLICATION = 'my-project.routing.application'
      CHANNEL_LAYERS = {
          'default': {
              'BACKEND': 'channels_redis.core.RedisChannelLayer',
              'CONFIG': {
                  "hosts": [(REDIS_URL, REDIS_PORT)], # REDIS_URL:开发环境:服务器<ip>,K8s部署时,根据redis的<service_name>; REDIS_PORT : 6379
              },
          },
      }

       

  2. 配置路由
    1. 在my-project项目文件夹下面新建routing.py,(与上步中layer配置时的ASGI路径保持一致)
      from channels.auth import AuthMiddlewareStack
      from channels.routing import ProtocolTypeRouter, URLRouter
      import consumer.routing  # 下一步新建的消费者app
      
      application = ProtocolTypeRouter({
          'websocket': AuthMiddlewareStack(
              URLRouter(
                  consumer.routing.websocket_urlpatterns
              )
          ),
      })

       

3.Django消费者

  1. 创建consumer app
    python manage.py startapp consumer

     

  2. 在consumer文件目录下新建routing.py
    from django.conf.urls import url
    
    from consumer import consumer # 下一步新建的业务处理模块
    
    websocket_urlpatterns = [
        url(r'^ws/monitoring/(?P<group_name>[^/]+)', consumer.MyConsumer.as_asgi())
    ]

     

  3. 在consumer文件目录下新建consumer.py 作为消费者业务处理模块
    class MyConsumer(AsyncWebsocketConsumer):
        async def connect(self):
            self.group_name = self.scope['url_route']['kwargs']['group_name'] # group_name 与routing.py中配置的参数保持一致
    
            # 收到连接时候处理,
            await self.channel_layer.group_add(
                self.group_name,
                self.channel_name
            )
            await self.accept()
    
        async def disconnect(self, close_code):
            # 关闭channel时候处理
            await self.channel_layer.group_discard(
                self.group_name,
                self.channel_name
            )
    
        # 收到消息 公司项目是单向推送的,所以没有测试接收消息的片段,有需要的话自己测试下吧,欢迎反馈
        async def receive(self, text_data):
            text_data_json = json.loads(text_data)
            message = text_data_json['message']
            print("收到消息--》", message)
            # 发送消息到组
            await self.channel_layer.group_send(
                self.chat_group_name,
                {
                    'type': 'client.message',
                    'message': message
                }
            )
    
        # 处理客户端发来的消息
        async def client_message(self, event):
            message = event['message']
            # 发送消息到 WebSocket
            await self.send(text_data=json.dumps({
                'message': message
            }))

     

  4. 发送消息示例,新建send_channel_msg.py,可以在其他模块进行调用
    from channels.layers import get_channel_layer
    from asgiref.sync import async_to_sync
    
    channel_layer = get_channel_layer()
    
    
    def send_channel_msg(group_name, msg):
        async_to_sync(channel_layer.group_send)(group_name,{"type": "client.message", "message": msg})
    

     

 4.K8s部署

  1. 能力有限,只会通过Rancher进行部署
  2. 将所有文件 打包成Docker镜像,推荐Dockerfile
  3. Rancher ->Workloads->Deploy,部署后端服务代码,正确填写镜像名称及版本号(redis:6.2.1,及自己的镜像名称),添加端口映射
  4. Rancher-> Load Balancing->add ingress,填写path及workload,填写后端服务的端口号