这次要藉由websocket做出网站实时的线上人数,关于django的websocket设定就不赘述了,网路上已经有相当多的资源,就写一些重点当笔记 ~
一、template
一开始最重要的就是要了解WebSocket支援的四个讯息:onopen,onmessage,onclose和onerror,然后根据你的需求去调用:
onopen:当浏览器跟websocket连线成功就可以在console看到"open"讯息,反之,连线失败则适用于onerror。
<body> <h1 id="app">{{ text }}</h1> <script> var socket = new WebSocket('ws://' + window.location.host + '/ws/online_number/'); socket.onopen = function(e){ console.log ("open", e); } socket.onerror = function(e){ console.log ("error", e) } socket.onmessage = function(e){ var data = JSON.parse(e.data); var message = data['message']; console.log("message",e); document.querySelector('#app').innerText = message; } </script></body>
二、consumers.py
我的想法很简单,只要使用者一进入网站就都放在同一个group里面,如下图的灰底部分,反之使用者一离开网站,他的资料就不会再存在于redis,然后只要再去抓取redis里的数目就会知道实时的人数了,
那要怎么实时的在网站显示线上使用人数呢?这边有个重点就是channel_layer.group_send,首先要知道传送到哪个group(这边room_group_name是users),再来就是要传送到前端的资料(这边一定要写成字典的形式),type为指定讯息处理的函式(number),这边就是处理成传个json,message为从redis得出的人数。
用redis_connect.zcard得出在group里的数量即代表线上人数。
小结:connect跟disconnect时都要做差不多的操作来反映出实时的人数。
class NumberOfOnline(AsyncWebsocketConsumer): db = Redis(host='127.0.0.1', port=8000, db=0) async def connect(self): await self.accept() self.room_group_name = 'users' await self.channel_layer.group_add(self.room_group_name, self.channel_name) redis_connect = get_redis_connection('default') online_number = str(redis_connect.zcard("asgi:group:users")) print('线上人数', online_number) await self.channel_layer.group_send(self.room_group_name,{'type':'number', 'message':online_number}) async def disconnect(self, close_code): await self.channel_layer.group_discard('users', self.channel_name) user = self.scope['user'] redis_connect = get_redis_connection('default') online_number = str(redis_connect.zcard("asgi:group:users")) print('线上人数', online_number) await self.channel_layer.group_send(self.room_group_name,{'type':'number', 'message':online_number}) async def number(self, event): message = event['message'] await self.send(text_data=json.dumps({ 'message': message }))
到目前为止只在本机测试,之后部署的话要开始研究asgi server的部分,django目前有提供daphne、Hypercorn、Uvicorn。可能会先试试daphne,但官方文件提供的资讯就只有下图这样:
感觉会遇到的坑不少...总之就先来try看看吧 ~