<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何設(shè)計(jì)一個(gè)在線觀看人數(shù)功能

          共 5087字,需瀏覽 11分鐘

           ·

          2022-01-05 00:32

          前言

          由于bilibili一直都有稿件在線觀看人數(shù)的功能,想了解他是如何做到的,因此有了這篇筆記。

          1、架構(gòu)選型

          常用的技術(shù)架構(gòu)

          1. 通過Url對access_log等日志記錄進(jìn)行篩選,通過日期分割等操作實(shí)現(xiàn)。

            • 實(shí)現(xiàn)容易,只需要文本讀取

            • 實(shí)時(shí)性不高

            • IO要求高

            • 缺點(diǎn)

            • 優(yōu)點(diǎn)

          2. WebSocket+Redis

            • 實(shí)時(shí)性高

            • 要求服務(wù)器性能

            • 實(shí)現(xiàn)稍微復(fù)雜

            • 缺點(diǎn)

            • 優(yōu)點(diǎn)

          Bilibili采用的方案(猜測)

          1. 通過對network進(jìn)行查看,可以看到Bilibili采用的方案是第二種,使用WebSocket的方式

          2. Bilibili 采用 連接 wss://broadcast.chat.bilibili.com:7826/sub 服務(wù)。

          3. 根據(jù)別人的開源來看,應(yīng)該是傳輸了這么一段東西,以下稱為[data1]

            0x00, 0x00, 0x00, 0x5B, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07,
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7B, 0x22, 0x72, 0x6F, 0x6F, 0x6D,
            0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x3A,
            0x2F, 0x2F, 0x35, 0x30, 0x33, 0x33, 0x34, 0x35, 0x38, 0x30, 0x2F, 0x38,
            0x38, 0x31, 0x32, 0x30, 0x37, 0x39, 0x32, 0x22, 0x2C, 0x22, 0x70, 0x6C,
            0x61, 0x74, 0x66, 0x6F, 0x72, 0x6D, 0x22, 0x3A, 0x22, 0x77, 0x65, 0x62,
            0x22, 0x2C, 0x22, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x22, 0x3A,
            0x5B, 0x31, 0x30, 0x30, 0x30, 0x5D, 0x7D
            復(fù)制代碼

            看起來是16進(jìn)制的byte數(shù)組,解析一下

             ? ?/**
            ? ? * 可以分析出
            ? ? * ? 0x00, 0x00, 0x00, 0x5B, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07,0x00, 0x00, 0x00, 0x01, 0x00, 0x00
            ? ? * ? 這一部分應(yīng)該是定義的消息頭,無法解析出實(shí)際的意義
            ? ? * 剩下的部分,解析后是
            ? ? * {"room_id":"video://50334580/88120792","platform":"web","accepts":[1000]}
            ? ? */
            ? ?@Test
            ? ?public void test3() {
            ? ? ? ?byte[] bytes = {
            ? ? ? ? ? ? ? 0x7B, 0x22, 0x72, 0x6F, 0x6F, 0x6D,
            ? ? ? ? ? ? ? ?0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x3A,
            ? ? ? ? ? ? ? ?0x2F, 0x2F, 0x35, 0x30, 0x33, 0x33, 0x34, 0x35, 0x38, 0x30, 0x2F, 0x38,
            ? ? ? ? ? ? ? ?0x38, 0x31, 0x32, 0x30, 0x37, 0x39, 0x32, 0x22, 0x2C, 0x22, 0x70, 0x6C,
            ? ? ? ? ? ? ? ?0x61, 0x74, 0x66, 0x6F, 0x72, 0x6D, 0x22, 0x3A, 0x22, 0x77, 0x65, 0x62,
            ? ? ? ? ? ? ? ?0x22, 0x2C, 0x22, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x22, 0x3A,
            ? ? ? ? ? ? ? ?0x5B, 0x31, 0x30, 0x30, 0x30, 0x5D, 0x7D
            ? ? ? };
            ? ? ? ?StringBuilder result = new StringBuilder();
            ? ? ? ?for (int index = 0, len = bytes.length; index <= len - 1; index += 1) {
            ? ? ? ? ? ?int char1 = ((bytes[index] >> 4) & 0xF);
            ? ? ? ? ? ?char chara1 = Character.forDigit(char1, 16);
            ? ? ? ? ? ?int char2 = ((bytes[index]) & 0xF);
            ? ? ? ? ? ?char chara2 = Character.forDigit(char2, 16);
            ? ? ? ? ? ?result.append(chara1);
            ? ? ? ? ? ?result.append(chara2);
            ? ? ? }
            ? ? ? ?System.out.println(new String(new BigInteger(result.toString(), 16).toByteArray()));
            ? }
            復(fù)制代碼
            1. 重點(diǎn)應(yīng)該在room_id,這里video分為兩部分,50334580應(yīng)該是視頻對應(yīng)的av號(hào)(現(xiàn)在使用了bv號(hào),但是實(shí)際上還是有對應(yīng)的av號(hào)的),88120792這里應(yīng)該是視頻的彈幕信息cid

            2. 根據(jù)代碼來看,應(yīng)該是只有一個(gè)連接地址

              aid/cid 作為了一個(gè)key,點(diǎn)擊視頻連接后,進(jìn)行websocket連接,然后發(fā)送[data1],然后服務(wù)器返回

              b'\x00\x00\x00+\x00\x12\x00\x01\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00{"code":0,"message":"ok"}'

            3. 之后會(huì)發(fā)送一個(gè)base64編碼過的用戶信息之類的?這里我沒看懂代碼,然后就返回了

              b'\x00\x00\x00n\x00\x12\x00\x01\x00\x00\x00\x03\x00\x00\x00\t\x00\x00{"code":0,"message":"0","data":{"room":{"online":3,"room_id":"video://85919470/146861497"}}}'

          2、我的方案-Java

          1. 采用Webscoket連接,用戶訂閱/video/{vid}

          2. 根據(jù)vid創(chuàng)建對應(yīng)的Map存儲(chǔ),vid和對應(yīng)的websocket-session

          3. 發(fā)送給后臺(tái)消息,帶有用戶的userId

          4. 根據(jù)vid發(fā)送到Redis,利用視頻的vid作為key,使用Redis的set數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)userId,通過scard key 查看在線人數(shù)

          5. 通過heatbeat刷新,或者定時(shí)刷新。

          6. 用戶關(guān)閉標(biāo)簽,斷開websocket服務(wù),帶上vid告知,移除Redis中的對應(yīng)的vid作為key的userId

          3、不足

          由于可能存在用戶同時(shí)打開多個(gè)同一個(gè)視頻的情況,這時(shí)如果關(guān)閉,其中一個(gè),則其他也會(huì)斷開連接,無法時(shí)時(shí)推送最新的在線觀看人數(shù)。

          參考的代碼 github.com/penpen456/b…

          import websocket
          import base64
          import requests
          import json
          import datetime
          import time

          def get_cid(av):
          ? ?response = requests.get("https://api.bilibili.com/x/web-interface/view?aid=" + str(av))
          ? ?response.encoding = 'utf-8'
          ? ?res = response.text
          ? ?# print(res)
          ? ?data = json.loads(res)
          ? ?c = data['data']['cid']
          ? ?# print(c)
          ? ?return c

          def make_send(av):
          ? ?cid = str(get_cid(av))
          ? ?res = b'\x00\x00\x00\\x00\x12\x00\x01\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00{"room_id":"video://' + str(av).encode('utf-8') + '/'.encode('utf-8') + cid.encode('utf-8') + '","platform":"web","accepts":[1000]}'.encode('utf-8')
          ? ?return res

          def get_online(text):
          ? ?cache = text.find(b'"online":')
          ? ?# print(cache)
          ? ?cache2 = text[cache+9:].find(b',')
          ? ?get = int(text[cache+9:cache2+9+cache])
          ? ?print(get)
          ? ?return get


          def connect(plz):
          ? ?url = "wss://broadcast.chat.bilibili.com:7823/sub"
          ? ?normal = base64.b64decode('AAAAIQASAAEAAAACAAAACQAAW29iamVjdCBPYmplY3Rd')
          ? ?ws = websocket.create_connection(url,timeout=10)
          ? ?ws.send(bytes(plz))
          ? ?get = ws.recv()
          ? ?print(get)
          ? ?print(normal)
          ? ?ws.send(bytes(normal))
          ? ?get = ws.recv()
          ? ?print(get)
          ? ?if get.find(b'online') != -1:
          ? ? ? ?# online = get_online(get)
          ? ? ? ?online=get_online(get)
          ? ? ? ?return online
          ? ?else :
          ? ? ? ?print("None")

          def get_online_from_av(av):
          ? ?send = make_send(av)

          ? ?online = connect(send)

          ? ?return online


          def write_file(onlines,times):
          ? ?
          ? ?with open(file_name,'a') as file_obj:
          ? ? ?file_obj.write(str(times) + ',' + str(onlines) + '\r')



          get_online_from_av(85919470)

          # file_name = str(input("File_Name(a.txt):"))
          # avid = int(input('AVid(85919470):'))




          # while True:
          ? ?
          # ? ? online=get_online_from_av(avid)
          # ? ? now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
          # ? ? print(now_time)
          # ? ? # write_file(online,now_time)

          ? ?
          # ? ? time.sleep(60)


          作者:ClassLoader
          鏈接:https://juejin.cn/post/6991085092110073863
          來源:稀土掘金
          著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



          瀏覽 90
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  综合在线视频网 | 亚洲黄色成人视频网站 | 久久精品熟女 | 日韩无码av观看 日韩无码高清网站 | 国产免费无码不卡看小穴 |