业务需求
大家好,我终于踩坑了哈哈哈哈~~~
如果服务器是单线程的话 消息推送完全可以用websocket来实现,参考我上一个文章 websocket消息发送
但是呢我这个上到测试环境就出现了问题,推送的消息偶尔能收到,偶尔收不到的情况 ,绞尽脑汁,最后问题是服务器采用集群的模式,是多线程的,所以就--------这时候redis就起作用了
现在的方法就是:通过 redis 来 广播消息,当 后台管理 请求, 要发送消息到 安卓端时, 你的 server ,把这个消息 发送到 redis,redis 再 发送到 所有的 server 上, server1, server2, server3
参考文档 Redis 发布订阅
实现方法(koa)
流程
1.首先客户端的消息发送到redis上,然后将发送的消息内容值publish到 chat频道
const Redisdb = require('ioredis')
module.exports = class Redis {
constructor () {
this.config = {
port: 6379,
host: process.env.REDIS_HOSTNAME || 'redis',
password: process.env.REDIS_PASSWORD || null,
db: process.env.REDIS_DATABASE || 1
}
this.client = new Redisdb(this.config)
}
//传入需要下发的消息
async pub (messageId, name, tourguide, content) {
const confi =
{
type: 'TEXT',
messageId: messageId,
name: name,
content: content,
targets: tourguide
}
const rustu = JSON.stringify(confi) // 将json转化成string
console.log(rustu)
this.client.publish('chat', rustu)// client将文本发布到chat这个频道
// 然后订阅这个频道的订阅者就会收到消息
}
}
2.readRedis.js文件此前一直在监听chat频道,readRedis.js文件接收到member后,通过socket将数据传到app 端
const Redisdb = require('ioredis')
const Sockets = require('../../socket/sockets')
const sockets = Sockets.getInstance()
module.exports = class ReadRedis {
constructor () {
this.config = {
port: 6379,
host: process.env.REDIS_HOSTNAME || 'redis',
password: process.env.REDIS_PASSWORD || null,
db: process.env.REDIS_DATABASE || 1
}
this.client = new Redisdb(this.config)
}
getRedisData () {
// 客户端连接redis成功后执行回调
this.client.on('ready', function () {
console.log('ready')
// 订阅消息
})
this.client.subscribe('chat')
console.log('订阅成功。。。')
this.client.on('error', function (error) {
console.log('Redis Error ' + error)
})
this.client.on('connect', function () {
console.log('redis connect ok')
})
// 监听订阅成功事件
this.client.on('subscribe', function (channel, count) {
console.log('client subscribed to ' + channel + ',' + count + 'total subscriptions')
})
// 收到消息后执行回调,message是redis发布的消息
this.client.on('message', function (channel, message) {
console.log('我接收到信息了' + message)
//消息通过socket发送到app
if (sockets.getAll().size === 0) {
// 先判断是否有设备连接 在决定是否发送,避免内存元泄漏
console.log('已经连接的安卓设备数量为0,群发失败')
} else {
console.log('asd12d')
for (const socket of sockets.getAll().values()) {
console.log('12的多大')
socket.emit('message', {
type: 'TEXT',
messageId: message.messageId,
name: message.name,
content: message.content,
targets: message.tourguide
})
}
}
})
}
}
3.在开启项目时 需要开启.readRedis.js文件中getRedisData方法