จำนวนคนออนไลน์และผู้ชม
แสดงจำนวนคนที่ออนไลน์หรือกำลังดู นับผู้ใช้ไม่ซ้ำด้วย presence และอ่านจำนวนคนของทุกห้องจากเซิร์ฟเวอร์ด้วย HTTP API และ webhook
“ออนไลน์ 1,284 คน” “กำลังดู 38 คน” “ห้องเต็ม”: ตัวเลขคนแบบสดทำให้ผลิตภัณฑ์ดูคึกคัก และตัวเลขเดียวกันนี้ก็บอกทีมของคุณว่าห้องไหนกำลังร้อนแรง เมื่อไรควรเพิ่มผู้ดูแล และช่วงพีคตอนค่ำสูงแค่ไหน คุณไม่ต้องนับการเชื่อมต่อเอง Hibira รู้อยู่แล้วว่าใครสมัครรับข้อมูลในแต่ละช่อง และโปรโตคอล Pusher มีสี่วิธีให้คุณถาม
สิ่งที่ผู้ใช้ได้รับ
- ตัวเลข “ออนไลน์” หรือ “กำลังดู” ที่ขยับตามคนที่เข้าและออก
- แถวรูปโปรไฟล์พร้อม “และอีก 120 คน” โดยคนที่เปิดสองแท็บนับเป็นคนเดียว
- ห้องที่บอกว่า “เต็ม” ก่อนจะมีใครพยายามเข้า
- สำหรับทีมของคุณ: หน้าผู้ดูแลที่แสดงห้องที่คนเยอะที่สุด และประวัติช่วงพีค

ฟีเจอร์ที่ใช้
- จำนวนผู้สมัครรับข้อมูล (
pusher:subscription_count) สำหรับตัวเลขในเบราว์เซอร์บนช่องสาธารณะและช่องส่วนตัว - ช่อง presence (
presence-) สำหรับนับผู้ใช้ไม่ซ้ำ และ ช่อง presence ขนาดใหญ่ (presence-large-) สูงสุด 100,000 คน - HTTP API (
GET /channels) เพื่ออ่านตัวเลขจากเซิร์ฟเวอร์ของคุณได้ทุกเมื่อ - Webhook (
member_added,member_removed,subscription_count) เพื่อรับแจ้งเมื่อจำนวนเปลี่ยน จะได้เก็บประวัติไว้
ในเบราว์เซอร์
pusher:subscription_countเซิร์ฟเวอร์ของคุณถาม
GET /channels?info=user_countเซิร์ฟเวอร์ของคุณได้รับแจ้ง
member_addedนับการเชื่อมต่อหรือนับคน?
นี่คือตัวเลขสองแบบที่ต่างกัน ควรเลือกอย่างตั้งใจ:
subscription_countนับการเชื่อมต่อ คนที่เปิดสามแท็บถูกนับสามครั้ง ใช้ได้บนช่องสาธารณะและช่องส่วนตัวโดยไม่ต้องลงชื่อเข้าใช้ จึงเหมาะกับตัวนับ “กำลังดู” บนหน้าสาธารณะuser_countนับผู้ใช้ไม่ซ้ำบนช่อง presence ตามuser_idที่เซิร์ฟเวอร์ของคุณลงนาม สองแท็บ หรือโทรศัพท์กับแล็ปท็อป นับเป็นคนเดียว ใช้เมื่อ “คน” คือสิ่งสำคัญ เช่น จำนวนที่นั่งสูงสุดหรือรายชื่อคนออนไลน์
ขั้นที่ 1: ตัวเลขในเบราว์เซอร์
เปิด ส่งจำนวนผู้สมัครรับข้อมูล ในการตั้งค่าแอป จากนั้นผู้สมัครรับข้อมูลทุกคนของช่องสาธารณะหรือช่องส่วนตัวจะได้รับจำนวนปัจจุบัน ไม่เกินวินาทีละครั้งระหว่างที่มันเปลี่ยน:
const stream = pusher.subscribe('stream-42');
stream.bind('pusher:subscription_count', ({ subscription_count }) => {
watching.textContent = subscription_count.toLocaleString();
});ไม่ต้องเขียนโค้ดก็ได้ สคริปต์ฝังบรรทัดเดียว ทำสิ่งเดียวกัน: <span data-hibira-online="stream-42">0</span> คนกำลังดู
ขั้นที่ 2: นับคนด้วย presence
บนช่อง presence ทุกคนได้รับรายชื่อสมาชิก ดังนั้นตัวเลขอยู่ในเบราว์เซอร์แล้ว:
const room = pusher.subscribe('presence-room-' + roomId);
const show = () => online.render(room.members.count, room.members);
room.bind('pusher:subscription_succeeded', show);
room.bind('pusher:member_added', show);
room.bind('pusher:member_removed', show);ช่อง presence รองรับสูงสุด 100 คน เพราะสมาชิกทุกคนได้รับการเข้าร่วมทุกครั้ง สำหรับทั้งเว็บไซต์หรืออีเวนต์ใหญ่ ให้ทุกหน้าเข้าร่วมช่อง presence ขนาดใหญ่ช่องเดียวด้วย @hibira-io/large-presence รองรับสูงสุด 100,000 คน และส่งจำนวนที่แม่นยำพร้อมตัวอย่างผู้ที่อยู่ วินาทีละครั้ง:
import { LargePresence } from '@hibira-io/large-presence';
const site = LargePresence.subscribe(pusher, 'presence-large-site', { maxMembers: 12 });
site.on('ready', ({ count }) => badge.render(count, site.members));
site.on('change', ({ count }) => badge.render(count, site.members));ขั้นที่ 3: ถามจากเซิร์ฟเวอร์ของคุณ
เซิร์ฟเวอร์ของคุณอ่านตัวเลขเดียวกันได้ผ่าน HTTP API ด้วยไลบรารีฝั่งเซิร์ฟเวอร์ที่เข้ากันได้กับ Pusher ตัวใดก็ได้ หนึ่งช่อง:
const res = await pusher.get({
path: '/channels/presence-room-42',
params: { info: 'user_count,subscription_count' },
});
const { occupied, user_count, subscription_count } = await res.json();ทุกห้องในครั้งเดียว เรียงจากคนเยอะที่สุด:
const res = await pusher.get({
path: '/channels',
params: { filter_by_prefix: 'presence-room-', info: 'user_count' },
});
const { channels } = await res.json();
// { "presence-room-7": { "user_count": 42 }, "presence-room-9": { "user_count": 17 } }
const busiest = Object.entries(channels)
.map(([name, { user_count }]) => ({ name, users: user_count }))
.sort((a, b) => b.users - a.users);หากต้องการตรวจจำนวนที่นั่งก่อนลงนามการสมัครรับข้อมูล ให้อ่านจำนวนคนในห้องที่เส้นทางยืนยันสิทธิ์ช่อง และปฏิเสธเมื่อห้องเต็ม:
app.post('/pusher/auth', requireLogin, async (req, res) => {
const { socket_id, channel_name } = req.body;
const room = await pusher.get({ path: `/channels/${channel_name}`, params: { info: 'user_count' } });
const { user_count } = await room.json();
if (user_count >= 8) return res.status(403).json({ error: 'room_full' });
res.json(pusher.authorizeChannel(socket_id, channel_name, { user_id: req.user.id, user_info: { name: req.user.name } }));
});และเมื่อเผยแพร่ คุณถามได้ว่าตอนนั้นมีกี่การเชื่อมต่อที่สมัครรับข้อมูลอยู่ ซึ่งบอกว่าอีเวนต์ไปถึงกี่คน:
const sent = await pusher.trigger('stream-42', 'goal', { minute: 81 }, { info: 'subscription_count' });
const { channels } = await sent.json();
console.log(`reached ${channels['stream-42'].subscription_count} viewers`);user_count ขอได้เฉพาะบนช่อง presence และในรายการช่องต้องใช้ filter_by_prefix=presence- การรวมจำนวนคนของหลายห้องจะนับซ้ำคนที่อยู่สองห้องพร้อมกัน หากต้องการจำนวนคนไม่ซ้ำทั้งเว็บไซต์ ให้อ่าน GET /channels/presence-large-site?info=user_count แทน
ขั้นที่ 4: เก็บประวัติด้วย webhook
หากต้องการวาดกราฟช่วงพีคตอนค่ำ หรือส่งการแจ้งเตือนเมื่อห้องว่าง ให้ Hibira แจ้งเซิร์ฟเวอร์ของคุณ ในพอร์ทัล เพิ่ม webhook สำหรับ member_added และ member_removed (ช่อง presence), subscription_count (ช่องสาธารณะและส่วนตัว เมื่อเปิดการนับ) หรือ channel_occupied และ channel_vacated:
app.post('/hibira/webhooks', express.text({ type: '*/*' }), async (req, res) => {
const webhook = pusher.webhook({ headers: req.headers, rawBody: req.body });
if (!webhook.isValid()) return res.sendStatus(401);
for (const e of webhook.getEvents()) {
if (e.name === 'member_added') await db.online.add(e.channel, e.user_id);
if (e.name === 'member_removed') await db.online.remove(e.channel, e.user_id);
if (e.name === 'subscription_count') await db.viewers.record(e.channel, e.subscription_count);
}
res.sendStatus(200);
});เคล็ดลับ
- การอ่านตัวเลขไม่ใช้โควตาข้อความ มีเพียงอีเวนต์ที่เผยแพร่เท่านั้นที่นับเป็นข้อความ ถึงอย่างนั้น ควรแคชคำตอบของ HTTP API ไว้บนเซิร์ฟเวอร์สักสองสามวินาที แทนที่จะถามทุกครั้งที่มีการเปิดหน้า
- Webhook อาจมาช้าหรือมาซ้ำ ใช้มันสำหรับประวัติและการแจ้งเตือน และอ่าน HTTP API เมื่อต้องการตัวเลขที่แม่นยำตอนนี้
- บนหน้าสาธารณะที่คนเยอะ ให้แสดงตัวเลขแบบปัดเศษ (“ออนไลน์ 1.2k”) มันขยับน้อยกว่าและยังรู้สึกมีชีวิตชีวา
- ตัวเลขแยกตามแอป หากคุณมีแอปทดสอบและแอปจริง แต่ละแอปเห็นเฉพาะการเชื่อมต่อของตัวเอง
- แพ็กเกจจำกัดการเชื่อมต่อพร้อมกัน ไม่ใช่จำนวนคน: ดูพีคที่แต่ละแพ็กเกจรองรับได้ที่ราคา