近日遇到需要发消息的情况,脑中直接浮现了kafka和emq(rabbitMQ)工具。
但是我仔细一想,发现了问题:
1.这次需要的消息功能非常简单,用量也不大
2.服务器的内存和硬盘都很小,还是单节点,kafka和mq这种会对服务器造成压力,而且有大材小用的意思
3.忽然间想起了redis也有消息队列的功能。
查询了一下,决定使用jedis的JedisPubSub。
和网上的例子不同的是,他们的是在服务器启动的时候直接订阅了channel,再也不会改变。
而我需要的是在用户登陆的时候,每个用户订阅属于自己特定的channel。
主要的过程是:
1.登陆后传入userid,使用jedis.subscribe订阅特定的channel;
2.使用JedisPubSub的onMessage接收消息;
解决的难点有:
1.jedis的pub和sub是阻塞的(例如onsubscribe),为此需要专门开辟线程进行处理
2.登陆后,订阅channel后,退出登陆,再次登陆,这时会重复订阅channel,导致收到多变消息;
2.1 jedis.unsubscribe不好用,一直在报client是null的错,解决方案是,在登陆的时候发送特定消息,在onMessage中判定加密后的特定字符串,如果相等,则在JedisPubSub的onMessage中直接调用unsubscribe取消订阅,这样直接就解决了jedis.unsubscribe的问题
3.在thread中无法正常注入jedisPool,只能在thread的构造方法中传入,其实,对于我的功能来说这是一个不错的方法,因为还需要传入别的参数
下面直接上代码,有问题可以联系我。
/**
登陆
**/
public class LoginController {
@Autowired
private MsgLauncher msgLauncher;
@PostMapping(value = "/login")
public Odin login(@RequestBody User user){
msgLauncher.prepared(u.getId());
msgLauncher.lanuch(u.getId());
return odin;
}
}
/**
消息登陆器
*/
package com.zzj.msg;
import com.zzj.msg.whistleRedis.WhistleRedisThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
/**
* Created by Administrator on 2019/1/7.
*/
@Service
public class MsgLaun