本文目录导读:

- 基于数据库最后活跃时间(适合传统Web应用)
- 基于Redis有序集合(适合高并发、实时要求高)
- 基于WebSocket连接数(适合实时页面,如聊天室)
- 基于反向代理日志(适合Nginx日志分析)
- 使用现成分析工具(零代码方案)
- 总结建议
统计在线用户数量通常需要根据应用场景和技术架构选择不同的方法,由于“在线”的定义不同(比如登录后算在线、页面活跃算在线、WebSocket连接算在线),实现方式也不一样。
以下是几种常见的脚本统计方案,从简单到复杂排列:
基于数据库最后活跃时间(适合传统Web应用)
原理: 用户每次请求时,更新数据库中该用户的 last_activity 时间戳,编写脚本查询近X分钟内(如5分钟)更新过的用户数量。
示例脚本(Python + MySQL):
import time
import mysql.connector
from datetime import datetime, timedelta
conn = mysql.connector.connect(host='localhost', user='root', password='pass', database='app')
cursor = conn.cursor()
# 定义在线时间窗口(5分钟内活跃视为在线)
online_window_minutes = 5
threshold_time = datetime.now() - timedelta(minutes=online_window_minutes)
query = "SELECT COUNT(DISTINCT user_id) FROM user_sessions WHERE last_activity > %s"
cursor.execute(query, (threshold_time,))
online_count = cursor.fetchone()[0]
print(f"当前在线用户数(基于5分钟活跃):{online_count}")
适用场景: 论坛、内容管理后台、ERP系统(对实时性要求不高)。
基于Redis有序集合(适合高并发、实时要求高)
原理: 用户心跳或请求时,向Redis有序集合写入当前时间戳作为score,脚本查询时间窗口内的唯一用户数。
示例脚本(Node.js + ioredis):
const Redis = require('ioredis');
const redis = new Redis();
async function getOnlineUsers(windowMinutes = 5) {
const now = Date.now();
const key = 'online_users'; // 有序集合的key
const threshold = now - windowMinutes * 60 * 1000;
// 1. 移除超时用户(可选,让集合保持干净)
await redis.zremrangebyscore(key, 0, threshold);
// 2. 统计当前窗口内用户数
const count = await redis.zcount(key, threshold, now);
return count;
}
// 模拟用户心跳(在实际代码中,每次用户请求时执行此操作)
// await redis.zadd('online_users', Date.now(), 'userId123');
getOnlineUsers().then(count => console.log(`当前在线人数:${count}`));
适用场景: 即时通讯、游戏、社交平台(需要精确统计当前活跃或连接中的用户)。
基于WebSocket连接数(适合实时页面,如聊天室)
原理: 用户在建立WebSocket连接时加入一个集合,断开时移除,脚本统计集合的大小。
示例脚本(Node.js + ws库):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// 存储所有连接的用户ID(在线用户集合)
const onlineUsers = new Set();
wss.on('connection', (ws, req) => {
// 连接时,假设通过URL参数或消息获取用户ID
const userId = new URL(req.url, 'http://localhost').searchParams.get('userId');
if (userId) {
onlineUsers.add(userId);
broadcastOnlineCount(); // 广播在线人数
}
ws.on('close', () => {
if (userId) {
onlineUsers.delete(userId);
broadcastOnlineCount();
}
});
});
function broadcastOnlineCount() {
const count = onlineUsers.size;
console.log(`当前在线用户数:${count}`);
// 可以向所有客户端广播更新
// wss.clients.forEach(client => client.send(JSON.stringify({ type: 'onlineCount', count })));
}
适用场景: 实时协作工具、直播弹幕、在线客服。
基于反向代理日志(适合Nginx日志分析)
原理: 直接解析Web服务器的访问日志,统计独立IP或用户Cookie,可以写一个定时脚本(如cron)执行分析。
示例脚本(Bash + awk):
#!/bin/bash
# 分析最近5分钟的Nginx访问日志,统计独立IP
LOG_FILE="/var/log/nginx/access.log"
MINUTES=5
# 获取当前时间戳(秒),计算5分钟前的秒数
NOW=$(date +%s)
THRESHOLD=$((NOW - MINUTES * 60))
# 解析日志(假设日志格式为:IP - - [timestamp] ...)
# 这里简单用date转换日志时间,可能需要根据你的日志格式调整
awk -v threshold="$THRESHOLD" '{
# 假设时间戳在日志的第四个字段,格式为 [09/May/2024:10:30:00 +0000]
# 需要转换为Unix时间戳进行比较,这里简化处理
# 实际可能需要用 gawk 的 strftime 或外部脚本
print $1 # 提取IP
}' $LOG_FILE | sort | uniq | wc -l
适用场景: 无状态API、静态站点、不想修改业务代码的后台统计。
使用现成分析工具(零代码方案)
如果不想写脚本,可以使用第三方服务或开源工具:
- Google Analytics: 通过“实时报告”查看当前在线人数(页面活跃用户)。
- Matomo: 开源网站分析,内置“实时访客”功能。
- Umami: 轻量级开源统计,可直接部署。
总结建议
| 方案 | 实时性 | 精确度 | 开发成本 | 适合场景 |
|---|---|---|---|---|
| 数据库时间戳 | 低(分钟级) | 低 | 低 | 后台管理、中小型网站 |
| Redis集合 | 高 | 高 | 中 | 高并发、实时需求 |
| WebSocket连接 | 最高 | 最高 | 中 | 实时双向通信应用 |
| 日志分析 | 低 | 中 | 低 | 遗留系统、临时统计 |
| 第三方工具 | 中 | 中 | 无 | 通用网站统计 |
选择建议:
- 如果是需要给用户看的在线人数(如“当前XX人在看”),推荐 WebSocket + Redis 组合。
- 如果是运维或后台监控,推荐 Redis 有序集合 或 数据库心跳。
- 如果是不想改动业务代码的临时方案,可以分析访问日志或使用 Google Analytics。
如果你能提供更具体的应用场景(比如是网页、App、还是游戏服务器),我可以帮你细化脚本实现。