【博客大赛】100行js代码实现网站在线用户数量统计 nodejs + socket.io方案
2021-04-15 19:13
1056 查看
需求提出
公司的在线培训平台,需要增加一个新功能:实时统计当前在线的用户数量并在终端界面上显示,需要的时候可以查询当前在线的用户的明细。
有3种技术方案可以选用:
1)改动后台代码,在用户登录和退出时将用户在线信息记录到数据库中,通过查询数据库查询用户明细。这种方案稍微重了点,要改动原来后台的代码,这个功能的加入需要重新进行后台代码的更新和测试。总觉得不妥,实时性和准确性也难以保障。
2)使用消息队列(message queue),将用户登录和退出的消息实时分发给一个独立的记录器模块,由记录器进行在线用户的记录和保存。这种方案依赖消息队列消息传递的准确性和及时性。
3)采用socket.io技术,建立一个独立的微服务,进行在线用户的记录。socket.io具有轻量、易维护的特点,客户端具有自动重连机制,可以保障数据的准确性和及时性。
权衡后决定采用第3种方案。
技术方案
nodejs + socket.io
nodejs是后台运行环境,使用socket.io模块进行在线用户的记录和通信。
服务器端
代码
- 主程序代码 app.js
var express = require('express'); var app = express(); var http = require('http'); var server = http.createServer(app); var io = require('socket.io'); var ios = io.listen(server); var port = 86; server.listen(port); console.log("start server on port: " + port); //辅助函数,根据room名称获取room对象 function ioRoom(name){ return ios.nsps['/'].adapter.rooms[name]; } //socket.io handling ios.on('connection', function(socket){ console.log("new client connected..."); socket.on('user', function(roomName,data, callback){ if(!data) data= {}; socket.join(roomName); console.log("new user jioned " + roomName ); //保存用户数据 let room = ioRoom(roomName); if(!room.users){ room.users = {}; } socket.room = roomName; var ip = socket.handshake.address; if(socket.handshake.headers['x-forwarded-for'] != null){ ip = socket.handshake.headers['x-forwarded-for']; } data.socket_id = socket.id; data.client_ip = ip; data.addtime = (new Date()).getTime() / 1000; room.users[socket.id] = data; var count = Object.keys(room.users).length; var backdata = {user_num:count,room:roomName}; if(typeof callback === "function"){ callback(backdata); } //发送用户数给所有人 ios.to(socket.room).emit('online-number', backdata); }); //根据用户请求发送用户列表给客户端 socket.on('get-users', function(callback){ if(!socket.room){ console.log("user not jioned a room!"); return; } let room = ioRoom(socket.room); callback(room.users); }); // disconnect user handling socket.on('disconnect', function () { if(!socket.room){ return; } let room = ioRoom(socket.room); if(room){ var users = room.users; delete users[socket.id]; socket.leave(socket.room); var count = Object.keys(users).length; if(count>0){ var data = {user_num:count,room:socket.room}; ios.to(socket.room).emit('online-number', data); } } }); });
这个代码很好理解:
- 客户端与服务器建立连接后,首先发送一个"user"消息给服务器,汇报用户信息。用户信息可以包括任何需要记录的信息,如:用户姓名、用户编号、所在的分组或应用(room),当前访问的页面等。
- 服务器收到用户信息后记录到内存中,然后将在线用户总数发送给所有用户。
- 客户端可以随时通过发送“get-users”请求消息查询在线用户列表。这个功能很酷,可以看到在线用户详细列表。
- 依赖定义文件 package.json
package.json定义这个nodejs程序运行所依赖的组件,有个这个文件之后,可以通过npm命令来安装依赖包。
代码:
{ "name": "userCounter", "version": "1.0.0", "description": "a user counter nodejs app", "keywords": [ "NodeJS", "OnlineUserCounter", ], "author": "www.ruiboyun.com", "homepage": "http://www.ruiboyun.com/", "private": "false", "bundleDependencies": [ "passport.socketio" ], "dependencies": { "express": "3.2.*", "socket.io": "^1.3.5", "util": "^0.10.3" }, "license": "MIT" }
原文件拷贝到代码目录即可,后面使用。
部署与运行
- 首先正确安装nodejs,参见 https://blog.51cto.com/livestreaming/2314592
- 安装依赖包
在代码根目录(app.js和package.jso所在目录)运行命令:
npm install
-
修改服务端口
在上述app.js代码中,修改web服务端口,默认是86,确保各级防火墙开放该端口:var port = 86;
- 运行程序
node app.js
客户端
客户端代码就是网页代码啦,可以根据需要提交用户信息、显示用户数量和查询用户列表。
示例代码:
<!DOCTYPE html> <html> <head> <meta http-equiv='Content-Type' content='text/html; charset=utf-8' /> <link href="bootstrap.min.css" rel="stylesheet" type="text/css" /> <title></title> </head> <body> <a href=""> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> 在线用户 <span class="badge badge-danger" style="background-color: red;" id="user-count">12</span> </a> </body> </html> <script src="socket.io.js"></script> <script type="text/javascript"> var io_host = "www.myhost.com"; //输入正确的域名或IP,就是前面启动服务的那台机器的域名或IP var io_server = "http://" + io_host + ":86"; //注意端口 var socket = io(io_server); var room = location.host; /** *显示用户数量的代码 */ function readerUserNumber(data){ console.log(data); var divuser = document.getElementById("user-count"); if(divuser) { divuser.innerHTML = data.user_num; } } socket.on('connect', function(){ console.log("connected to server..."); //提交用户信息 var info = {}; info.url = location.href; info.username = "myname"; socket.emit("user",room,info,function(msg){ readerUserNumber(msg); }); //查询用户明细 socket.emit("get-users",function(data){ console.log("render by get-users..."); console.log(data); }); }); socket.on('disconnect', function(){ }); socket.on('online-number', function(data){ //用户数量更新 console.log("online number:"); readerUserNumber(data); }); </script>
效果提升
基于这个应用,还可以实现如下效果:
1)将在线用户数采样记录入库,用于网站热度分析和用户访问趋势分析
2)将用户访问历史记录如库,跟踪用户访问轨迹
3)提交用户信息时把昵称、头像等信息提交进来,显示用户列表时可以更酷
我的一个在线用户效果:
相关文章推荐
- J2EE使用session监听实现在线用户明细及数量统计
- 在设计网站时,网站被访问情况和用户使用情况是网站设计的一个重点。当需要评价网站价值时,网站访问量是一个重要参数。请结合使用Application对象和Session对象来统计当前在线用户数量
- 怎样在Asp.net中实现当前网站的访问用户数量统计
- Java 实现网站当前在线用户统计
- 利用HttpSessionListener实现网站在线人数统计功能
- 统计当前在线用户数、平均访问时长、在线用户最高数等实现
- 通过Socket.IO与nodeJs实现即时消息推送
- 用ASP.NET实现在线用户统计
- 使用监听器实现一个统计网站在线人数的示例
- java session HttpSessionListener、HttpSessionBindingListener使用区别,实现在线人数统计以及踢出用户
- ASP.NET中在线用户统计的简单实现及讨论
- 遇到的坑:在线用户统计的实现
- asp 实现同一帐号,防止多人同时登录、获取在线列表、实现登录日志(可用户统计在线时长),适合用户访问量大的系统
- 利用HttpSessionListener实现网站在线人数统计功能
- 用ASP.NET实现在线用户统计
- Jsp在线人数统计 - 实现后台强制前台某个用户退出
- 实现统计在线用户的几种方式
- asp实现一个统计当前在线用户的解决方案
- asp实现一个统计当前在线用户的解决方案
- ASP.NET中在线用户统计的简单实现及讨论