redis发布订阅广播模式的使用&结合jeecg的Redis网关路由刷新机制

这篇具有很好参考价值的文章主要介绍了redis发布订阅广播模式的使用&结合jeecg的Redis网关路由刷新机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

redis发布订阅广播模式的使用&结合jeecg的Redis网关路由刷新机制


本质和传统的消息发布和订阅机制是差不多的,但是相较于其他几款MQ产品,Redis的使用更加便捷,也更加轻量化,不需要搭建一套繁重的MQ框架。
但是也它致命的缺点,redis的消息不会被持久化,服务器出现问题,消息会丢失,导致数据问题。对于数据一致性要求比较高的场景不适合使用,需要慎重选择。


导致消息丢失的情况:


一般获取消息的客户端(订阅者)会通过while循环不断的向redis服务器请求发布者获取消息,假如发布者在订阅者退出订阅状态时发布了消息,则该消息会丢失。

关于这个订阅者退出状态,值得探讨,这里做一个分析。使用终端模拟时,假如订阅者断开连接后,又重新连接,在这个断开的时间段内,如果存在数据发布,则重新连接的客户端是无法获取到消息的,因为redis服务器认为它是一个纯新的客户端。因此在程序里,必须小心使用redis的订阅连接,当订阅的连接没有主动释放时,也没有执行退出订阅时,数据会源源不断的写入内存,直到所有订阅者取走消息。

优缺点

优点:便捷,轻量化
缺点:

  • 不稳定,消息易丢失,导致数据一致性问题,性能不高

  • redis客户端在订阅消息时,要求订阅在发布之前,否则无法订阅到客户端订阅前,已经发布的消息。

  • redis的消息发布与订阅,无法实现高并发和大数据量。前者受限于redis本身的并发量限制和内存大小;后者是因为redis发布消息时,会先将数据推送到每个客户端的连接缓冲区,如果单个消息过大会撑爆缓冲区,导致redis错误,就算redis没有撑爆缓冲区,如果消费者(订阅方)没有及时取走消息,也会因为数据积累而撑爆内存。

  • 总结,快捷方便,消息不会持久化,网络不稳定,断开重连,无法接受到已发布的消息,链接没有释放,也没有退出订阅,消息会一直在内存中积压,撑爆内存。

简单使用

命令:


psubscribe   订阅一个或者多个channel,使用正则方式匹配多个
publish    发布消息到指定channel
pubsub    查看订阅与发布系统状态
pubsub channels   pattern   列出当前活跃的channel
pubsub  numsub  channel-1  channel-n   获取指定频道的订阅者数量
pubsub  numpat  获取订阅模式的数量
subscribe      订阅一个或者多个channel消息,使用一个或者多个准确的channel名实现订阅
unsubscribe   客户端退订channel

springboot中使用

@Autowired
private RedisTemplate<String, Object> redisTemplate;

BaseMap params = new BaseMap();
params.put("handlerName", "loderRouderHandler");
//刷新网关
redisTemplate.convertAndSend(GlobalConstants.REDIS_TOPIC_NAME, params);

jeecg代码分析:

注册消息监听器适配器


//RedisConfig中配置MessageListenerAdapter适配器,自定义消息处理方法
@Bean
MessageListenerAdapter commonListenerAdapter(RedisReceiver redisReceiver) {
    MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(redisReceiver, "onMessage");
    messageListenerAdapter.setSerializer(this.jacksonSerializer());
    return messageListenerAdapter;
}

自定义消息接收器,

###在消息接收器中获取 JeecgRedisListener->onMessage()来获取消息,
###其他模块只需要实现JeecgRedisListener即可
###Object handlerName = params.get(“handlerName”),是消息内容传递过来的,可以动态指定是哪个消息处理类,比如路由处理类就是:GlobalConstants.LODER_ROUDER_HANDLER


@Component
public class RedisReceiver {
    public void onMessage(BaseMap params) {
        //获取redis消息处理类名称
        Object handlerName = params.get("handlerName");
        //通过SpringContextHolder拿到JeecgRedisListener
        JeecgRedisListener messageListener = (JeecgRedisListener)SpringContextHolder.getHandler(handlerName.toString(), JeecgRedisListener.class);
        if (ObjectUtil.isNotEmpty(messageListener)) {
            messageListener.onMessage(params);
        }
    }

    public RedisReceiver() {
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof RedisReceiver)) {
            return false;
        } else {
            RedisReceiver other = (RedisReceiver)o;
            return other.canEqual(this);
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof RedisReceiver;
    }

    public int hashCode() {
        int result = true;
        return 1;
    }

    public String toString() {
        return "RedisReceiver()";
    }
}

定义路由监听器,(路由处理器),通过监听redis来实现

@Slf4j
@Component(GlobalConstants.LODER_ROUDER_HANDLER)
public class LoderRouderHandler implements JeecgRedisListener {

    @Resource
    private DynamicRouteLoader dynamicRouteLoader;


    @Override
    public void onMessage(BaseMap message) {
        dynamicRouteLoader.refresh(message);
    }

}

最终通过下面的方法获取路由配置

/**
 * 从redis中读取路由配置
 *
 * @return
 */
private void loadRoutesByRedis(BaseMap baseMap) {
    List<MyRouteDefinition> routes = Lists.newArrayList();
    configService = createConfigService();
    if (configService == null) {
        log.warn("initConfigService fail");
    }
    Object configInfo = redisUtil.get(CacheConstant.GATEWAY_ROUTES);
    if (ObjectUtil.isNotEmpty(configInfo)) {
        log.info("获取网关当前配置:\r\n{}", configInfo);
        JSONArray array = JSON.parseArray(configInfo.toString());
        try {
            routes = getRoutesByJson(array);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }else{
        log.warn("ERROR: 从Redis获取网关配置为空,请确认system服务是否启动成功!");
    }
    
    for (MyRouteDefinition definition : routes) {
        log.info("update route : {}", definition.toString());
        Integer status=definition.getStatus();
        if(status.equals(0)){
            dynamicRouteService.delete(definition.getId());
        }else{
            dynamicRouteService.add(definition);
        }
    }
    if(ObjectUtils.isNotEmpty(baseMap)){
        String delRouterId = baseMap.get("delRouterId");
        if (ObjectUtils.isNotEmpty(delRouterId)) {
            dynamicRouteService.delete(delRouterId);
        }
    }
    this.publisher.publishEvent(new RefreshRoutesEvent(this));
}

参考链接:
https://www.cnblogs.com/lovelsl/articles/15272190.html文章来源地址https://www.toymoban.com/news/detail-419490.html

到了这里,关于redis发布订阅广播模式的使用&结合jeecg的Redis网关路由刷新机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot rabbitmq 发布订阅 广播模式

    根据amqp协议、rabbitmq入门、springboot集成rabbitmq 可知,rabbitmq的广播模式关键是使用fanout类型的exchange,fanout exchange会忽略message中的routing-key、queue中的binding-key,发给绑定exchange的全部queue。 实现发布订阅(广播模式)的关键在于对exchange类型的理解,可参考amqp协议、rabbitmq入门

    2024年02月02日
    浏览(30)
  • RabbitMQ的5种模式——再探RabbitMQ的模式,简单、工作,发布订阅(广播),路由、主题 & 页面分析

    RabbitMQ作为一款常用的消息中间件,在微服务项目中得到大量应用,其本身是微服务中的重点和难点,有不少概念我自己的也是一知半解,本系列博客尝试结合实际应用场景阐述RabbitMQ的应用,分析其为什么使用,并给出怎么用的案例。 本篇博客结合场景来阐述RabbitMQ的几种模

    2024年02月07日
    浏览(32)
  • Redis发布订阅

    Redis 发布订阅(pub/sub)是一种 消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 Redis 客户端可以订阅任意数量的频道。 订阅/发布消息图: 下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系: 当有新消息通过 PUBLISH

    2024年02月11日
    浏览(27)
  • Redis(03)——发布订阅

    基于频道 publish channel message:将信号发送到指定的频道 pubsub subcommand [argument [argyment]]:查看订阅或发布系统状态 subscribe channel [channel]:订阅一个或多个频道的信息 unsubscribe [channel [channel]]:退订指定的频道,若没有指定频道,则默认退订所有频道 基于模式 psubcribe pattern [pa

    2024年02月20日
    浏览(28)
  • redis发布订阅模型

    Redis 的发布订阅基于 publish , subscribe , psubscribe 订阅 发布 订阅 发布 订阅的状态的推进 向 new.it 发送消息 1.频道订阅和退订 Redis 订阅关系保存在服务器状态的 pubsub_channels 字典 key 为 channel , value 为链表,链表上有订阅该频道的 Client 如图所示 1.1订阅频道 subscribe Client 订阅 pu

    2024年02月13日
    浏览(24)
  • redis 发布和订阅

    目录 一、简介  二、常用命令 三、示例 Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。下图展示了频道 channel1 ,以及订阅这个频道的三个客户端 —— client1 、client2 和 client3 之间的关系: 当

    2024年02月12日
    浏览(28)
  • Redis发布订阅机制学习

    【IT老齐151】Redis发布订阅机制是如何实现的?_哔哩哔哩_bilibili go-redis的发布与订阅 - 知乎 (zhihu.com) 先输入   redis-server.exe   启动redis,否则对应接口不开放 再输入   redis-cli 命令启动客户端服务 当一个客户端c1去向redis订阅一个主题chatroom的时候,Redis内部就会创建一块空

    2024年02月09日
    浏览(32)
  • Redis 消息队列和发布订阅

    采用redis 三种方案: ● 生产者消费者:一个消息只能有一个消费者 ● 发布者订阅者:一个消息可以被多个消费者收到 ● stream模式:实现队列和广播模式 Producer调用redis的lpush往特定key里放消息,Consumer调用brpop去不断监听key。 1、利用redis的链表,存储数据,实现队列模式

    2024年01月18日
    浏览(31)
  • JAVA 实现 Redis 发布订阅

    发布订阅: 消息发布者发布消息 和 消息订阅者接收消息 ,两者之间通过某种媒介联系起来 例如订杂志,当自己订阅了爱格杂志,每个月会发刊一本。到发布的时候派送员将杂志送到自己手上就能看到杂志内容。只有我们订阅了该杂志才会派送给我们 Redis 发布订阅(pub/su

    2024年02月14日
    浏览(30)
  • Redis实现消息的发布和订阅

    4.1 发送消息 4.2 接收消息

    2024年02月13日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包