实时拍卖、比分与大量观众
把当前出价或比分同时推给成千上万名观众,让新进来的人立刻看到最新状态,并显示真实的“正在观看”人数。
实时拍卖、运动比分、益智节目、限时抢购和直播留言有一个共同点:成千上万的人在同一刻看同一件事,晚一秒就会改变结果。晚到的出价、落后转播的比分,都会把人送去别的地方。
用户得到什么
- 目前出价、比分或库存一变化就立刻看到。
- “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 的应用页面观察。