← 使用情境

即時拍賣、比分與大量觀眾

把目前出價或比分同時推給成千上萬名觀眾,讓新進來的人立刻看到最新狀態,並顯示真實的「正在觀看」人數。

即時拍賣、運動比分、益智節目、限時搶購和直播留言有一個共同點:成千上萬的人在同一刻看同一件事,晚一秒就會改變結果。晚到的出價、落後轉播的比分,都會把人送去別的地方。

使用者得到什麼

  • 目前出價、比分或庫存一變化就立刻看到。
  • 「12,408 人正在觀看」,一個真實而且會動的數字。
  • 一打開頁面就看到最新狀態,即使活動已經進行到一半。

用到的功能

  • 快取頻道(cache-),每位新進來的人立刻拿到目前的價格或比分,不必查你的資料庫。
  • 大型 presence 頻道(presence-large-),最多 100,000 名成員,提供即時人數與在場者樣本。
  • 訂閱人數(pusher:subscription_count),在公開頻道上顯示簡單的觀看人數。
  • 免費扇出:一筆出價發布給 20,000 名觀眾,只算一則訊息,不是 20,000 則。

步驟 1:每次變化只發布一次

你的伺服器檢查出價或記錄比分,然後把新狀態發布給所有人:

app.post('/auctions/:id/bids', requireLogin, async (req, res) => {
  const bid = await db.auctions.placeBid(req.params.id, req.user.id, req.body.amount); // rejects lower bids
  await pusher.trigger(`cache-auction-${req.params.id}`, 'bid', {
    amount: bid.amount,
    bidder: bid.displayName,
    endsAt: bid.endsAt,
  });
  res.json(bid);
});

永遠送完整狀態(目前金額與結束時間),不要送差異:漏掉一則事件的觀眾,在下一則事件時就會恢復正確。

步驟 2:顯示給觀眾

const auction = pusher.subscribe(`cache-auction-${id}`);
auction.bind('bid', ({ amount, bidder, endsAt }) => {
  price.set(amount);
  feed.prepend(`${bidder} bid ${amount}`);
  countdown.until(endsAt);
});

訂閱後馬上會收到快取的最後一筆出價,價格永遠不會是空白。

步驟 3:觀看人數

如果只需要人數,在應用程式設定裡開啟 傳送訂閱人數,並在同一個公開頻道上綁定人數事件:

auction.bind('pusher:subscription_count', ({ subscription_count }) => watching.set(subscription_count));

不寫程式也行,一行嵌入腳本可以做到同樣的事:<span data-hibira-online="cache-auction-42">0</span> watching。

如果還要顯示有誰在場,使用大型 presence 頻道與 @hibira-io/large-presence:

import { LargePresence } from '@hibira-io/large-presence';

const room = LargePresence.subscribe(pusher, `presence-large-auction-${id}`, { maxMembers: 50 });
room.on('ready', ({ count }) => audience.render(count, room.members));
room.on('change', ({ count }) => audience.render(count, room.members));

人數始終精確,成員的加入與離開則每秒合併成一則小更新送達,而不是每個人一則事件。

小提醒

  • 每筆出價、答案或購買都在你的伺服器上驗證。絕對不要讓用戶端自己發布活動的狀態。
  • 要規劃的是連線數,而不是訊息數:20,000 名觀眾就是 20,000 個同時連線,價格取決於尖峰。請看價格。
  • 像搶票開賣這種瞬間,每一兩秒發布一次庫存,而不是每賣出一張就發一次。
  • 大日子之前先用真實的觀眾規模測試:用壓力測試工具開大量連線,同時在 portal 的應用程式頁面觀察。