之前写过一篇使用laraval框架+node.js实现socket的文章,后台来了一个新的需求,每分钟定时上报连接数,需要node将链接发送到php,php每分钟上报一次;
我就想到了node这里把数据存到redis,然后php的定时任务每分钟从redis中取到连接数上报;
在取node写入redis的时候遇到了一些问题,在请教了node大拿之后解决了问题:
主要原因是:
redis客户端是个单例模式,发布订阅频道之后就不允许其它的操作(除(P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT之外,所以用作发布订阅之后,不能再用此实例写redis,所以就在重新实例化一个redis,做写入的处理;
// 常量
const port = 6001;
const evn = 'test';
// http server
let app = require('http').createServer((req, res) => {
res.writeHead(200);
res.end('');
});
// socket.io
let io = require('socket.io')(app);
// redis 连接
let Redis = require('ioredis');
let redisConfig = {};
if (evn === 'local') {
redisConfig = {
host: '127.0.0.1',
port: '6379',
password: null,
db: 0
};
} else if (evn === 'test') {
redisConfig = {
host: '47.94.*****0',
port: '**',
password: '******',
db: 0
};
}
const redis = new Redis(redisConfig);
const setRedis = new Redis(redisConfig);
// redis客户端是个单例模式,发布订阅频道之后就不允许其它的操作(除(P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT之外)
redis.psubscribe('news.*', (err, count) => {
// console.log('psubscribe-err', err);
// console.log('psubscribe-count', count);
});
redis.on('pmessage', (subscrbed, channel, message) => {
// console.log('pmessage-subscrbed', subscrbed);
// console.log('pmessage-channel', channel);
// console.log('pmessage-message', message);
message = JSON.parse(message);
console.log('[M]' + channel + ' Message :' + message.event, message.data);
io.emit(channel + ':' + message.event, message.data);
});
const keys = {
getRedisKey(key) {
return `onlinereport:${key}`;
},
};
let result = '';
const redisOption = {
getRedisValue(key) {
return setRedis.get(keys.getRedisKey(key), (err, res) => {
if (err) {
// console.log('err', err);
return;
}
// console.log('res', res);
result = res;
});
},
setRedisValue(key, value, expired) {
return setRedis.set(keys.getRedisKey(key), value, 'EX', expired);
}
};
// socket.io 部分
const userList = [];
function countUser() {
let userCount = [];
for (var i in userList) {
userCount[i] = userList[i].length;
}
return userCount;
}
function cookieToObject(data) {
let new_Object = [];
for (let i in data) {
data[i] = data[i].split('=');
new_Object[data[i][0]] = data[i][1];
}
return new_Object;
}
io.on('connection', (socket) => {
socket.on('login', (user) => {
if (userList[user.channel] === undefined) userList[user.channel] = [];
if(user.openid.indexOf("admin") == -1){
userList[user.channel].push(user.openid);
io.emit(user.channel + ':UserChange', userList[user.channel]);
let userCount = countUser();
io.emit('user.count', userCount);
console.log(user.channel)
console.log(userList[user.channel].length)
//当前在线人数写入缓存
redisOption.setRedisValue(user.channel,userList[user.channel].length,86400)
}
console.log('[L] openid:' + user.openid + ' Login!');
});
socket.on('disconnect', (res) => {
let cookie = socket.request.headers.cookie || '';
if (cookie){
let user = cookieToObject(cookie.split('; '));
let openid = user['openid'] + "";
if(openid.indexOf("admin") == -1){
let index = userList[user['channel']].indexOf(user['openid'] + "");
userList[user['channel']].splice(index, 1);
io.emit(user.channel + ':UserChange', userList[user.channel]);
let userCount = countUser();
io.emit('user.count', userCount);
redisOption.setRedisValue(user.channel,userList[user.channel].length,86400)
}
//当前在线人数写入缓存
console.log('[L] openid:' + user['openid'] + ' Logout!');
}
});
socket.on('user.count', () => {
let userCount = countUser();
io.emit('user.count', userCount);
});
});
redis.psubscribe('*', (err, count) => {
});
app.listen(port, () => console.log('Server is running!'));
// 加上未捕获异常
process.on('uncaughtException', (err) => {
console.log('uncaughtException', err);
process.nextTick(() => process.exit(1));
});