express redis socket 消息提醒方案

本文介绍了一种基于 Node.js 的实时消息推送方案,利用 Express、Redis 和 Socket.IO 实现跨项目的用户消息通知功能。该方案支持用户会话共享,通过轮询方式减轻服务器压力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

express redis socket 消息提醒方案:本地emit 轮循服务器获取redis 再推送

原创  2016年08月22日 11:00:54
  • 749

在做项目时,需要实现消息提醒,因为现在有多个项目,都需要实现。

为了实现多项目公用,和以后项目也可以使用。

单独开了个项目,起了个node 服务来实现消息提醒。

用express redis socket.io来实现的。

session 都存在redis里,所有的服务都一样。这样实现了,sessio共享

只要其他项目登录了,消息服务也就登录了。

因为要多个项目共用,所以会在项目中引用socket.io js 然后创建

var socket=io('http://localhost:8007');

链接到8007也就是消息服务器。

消息服务io connection 链接上后,通过socket.request.headers.sookie 来获取请求的cookie 找到connect.sid 得到sid。

再从redis上查找对应的用户信息。保存到链接socket上。然后发送emit open ,表示链接成功。

本地接收到后轮循向服务器发请message 请求来获取消息。

服务器查询redis获取消息,并emit 返回。


以下是服务端代码:

[html]  view plain  copy
  1. /*star 2016-8-20  
  2. socket 从请求中获取cookie 也就是token 再从redis里取到token对应的user 信息。  
  3. 这后向socket页面emit(open) 表示当前登录用户链接socket成功。  
  4. 本地轮循发起emit message 事件,获取用户的提示条数。  
  5. 服务器根据 userid 从redis里读取提示条数并返回。  
  6. ----此为node socket 消息服务器第一种解决方案  
  7. */  
  8. var express = require('express');  
  9. var path = require('path');  
  10. var cookieParser = require('cookie-parser');  
  11. var bodyParser = require('body-parser');  
  12. var session = require('express-session');  
  13. var RedisStore = require('connect-redis')(session);  
  14. var http = require('http');  
  15.   
  16. var redis_api=require('./redis_api.js')  
  17.   
  18.   
  19. var port=8007;  
  20. var app = express();  
  21.   
  22.   
  23.   
  24. // view engine setup  
  25. app.use(bodyParser.json());  
  26. app.use(bodyParser.urlencoded({ extended: false }));  
  27. app.use(cookieParser());  
  28. app.use(express.static(path.join(__dirname, 'public')));  
  29.   
  30. // 设置 Session  
  31. app.use(session({  
  32.   store: new RedisStore({  
  33.     host: "127.0.0.1",  
  34.     port: 6379,  
  35.     db: 0  
  36.     //pass: 'yu'  
  37.   }),  
  38.   resave:false,  
  39.   saveUninitialized:false,  
  40.   secret: 'keyboard cat'  
  41. }))  
  42.   
  43. app.use(function(req,res,next){  
  44.   console.log(req.url);  
  45.   next();  
  46. })  
  47.   
  48.   
  49.   
  50.   
  51. app.get('/socket',function(req,res){  
  52.     res.header("Access-Control-Allow-Origin", "*");  
  53.     //console.log(req.session.username)  
  54.     res.send(req.session)  
  55. })  
  56.   
  57.   
  58. var server = http.createServer(app);  
  59.   
  60. server.listen(port);  
  61. server.on('error', onError);  
  62. server.on('listening', onListening);  
  63.   
  64.   
  65. var io=require('socket.io')(server);  
  66. var users=[]  
  67. io.on('connection',function(socket){      
  68.     console.log('open')  
  69.     //获取请求cookie  
  70.     var cookie_string=decodeURIComponent(socket.request.headers.cookie)  
  71.     //正则匹配 获取sid  
  72.     var s=/connect.sid=([^\.]+)/g.exec(cookie_string);  
  73.     var sid='';  
  74.     if(s && s.length>1){  
  75.         sid=s[1].split(':')[1];  
  76.         //console.log(sid);  
  77.         var user;  
  78.         redis_api.getsid(sid,function(err,res){  
  79.             if(!err){  
  80.                 user=res;             
  81.                 socket.emit('open',{sid:sid,user:user.user})  
  82.                 socket.sid=sid;  
  83.                 socket.user=user.user;  
  84.                 //链接数测试  
  85.                 /*var n=9000000;  
  86.                 while(n--){  
  87.                     users.push(socket);  
  88.                 }*/  
  89.             }  
  90.         })  
  91.     }  
  92.     socket.on('message',function(res){  
  93.         console.log(res);  
  94.         switch(res.action){  
  95.             case "read":  
  96.                 read();  
  97.                 break;  
  98.         }  
  99.     })  
  100.     function read(){  
  101.         redis_api.getmessage(socket.user.id,function(err,reply){  
  102.             if(!err){  
  103.                 socket.emit('message',{type:1,action:'message',data:reply,number:users.length})  
  104.             }  
  105.         })  
  106.     }  
  107.     socket.on('disconnect',function(){  
  108.         console.log('close')  
  109.     })  
  110.       
  111. })  
  112.   
  113. function onError(error) {  
  114.   if (error.syscall !== 'listen') {  
  115.     throw error;  
  116.   }  
  117.   
  118.   var bind = typeof port === 'string'  
  119.     ? 'Pipe ' + port  
  120.     : 'Port ' + port;  
  121.   
  122.   // handle specific listen errors with friendly messages  
  123.   switch (error.code) {  
  124.     case 'EACCES':  
  125.       console.error(bind + ' requires elevated privileges');  
  126.       
  127.       break;  
  128.     case 'EADDRINUSE':  
  129.       console.error(bind + ' is already in use');  
  130.         
  131.       break;  
  132.     default:  
  133.       throw error;  
  134.   }  
  135. }  
  136.   
  137. /**  
  138.  * Event listener for HTTP server "listening" event.  
  139.  */  
  140.   
  141. function onListening() {  
  142.   
  143.  console.log('localhost:'+port)  
  144. }  
以下是redis_api代码

[html]  view plain  copy
  1. var redis   = require('redis');  
  2. var client  = redis.createClient('6379', '127.0.0.1');  
  3.   
  4.   
  5. exports.getsid=function(sid,call){  
  6.     //client.select('0',function(err){            
  7.             //if(!err){  
  8.                 //console.log('select 0',err)  
  9.                 client.get('sess:'+sid ,function(err,reply){  
  10.                     console.log('------sess:'+sid)  
  11.                     console.log('sess:',sid,err,reply)  
  12.                     console.log('end ------sess:'+sid)  
  13.                     if(err){  
  14.                         call(err)  
  15.                     }else{  
  16.                         //console.log('sess:'+sid+'=',reply)  
  17.                         call(0,JSON.parse(reply))  
  18.                     }                     
  19.                 })  
  20.             //}  
  21.     //})  
  22.   
  23. }  
  24. //根据userid 获取消息数  
  25. exports.getmessage=function(userid,call){  
  26.     client.select('0',function(err){  
  27.         if(!err){  
  28.             client.get('message:'+userid,function(err,reply){  
  29.                 if(!err){  
  30.                     console.log('message:'+userid+'='+reply)  
  31.                     call(0,JSON.parse(reply))  
  32.                 }  
  33.                 // 关闭链接  
  34.                 //client.quit();  
  35.             })  
  36.         }  
  37.     })  
  38. }  


以下是页面代码:

[html]  view plain  copy
  1. var socket=io('http://localhost:8007');  
  2.             socket.on('open',function(res){  
  3.                 console.log('开了',res)  
  4.                 time();  
  5.                 //socket.emit('message',{id:1,type:1,action:'read'})  
  6.             })  
  7.             socket.on('message',function(res){  
  8.                 console.log(res,new Date());  
  9.             })  
  10.   
  11.               
  12.             //以下为轮循发请emit 获取消息数  
  13.             function time(){  
  14.                 setInterval(function(){  
  15.                     socket.emit('message',{type:1,action:'read'})  
  16.                     //socket.emit('message',{type:1,action:'read'})  
  17.                 },3000)  
  18.             }  

当然这种实现是有问题 的,并不是时时消息提醒。

而且当链接数大时不断轮循会给服务器和带宽带来很大压力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值