RabbitMQ_v2.0

RabbitMQ_2.0

在这里插入图片描述


RabbitMQ高级特性


消息的可靠投递

简介:A通过消息队列给B发送一个消息,要经过以下过程(producer->rabbitmq broker->exchange->queue->consumer),RabbitMQ为了杜绝消息丢失以及投递失败,因而提供了两种方式来保证消息的投递可靠性。

  • confirm 确认模式 (从producer到exchange的消息都会返回一个confirmCallback)
  • return 退回模式(exchange路由到queue失败了 投递失败 才会返回returnCallback)
/*spring-rabbitmq-producer.xml*/

<!--消息可靠性投递(生产者)-->
<rabbit:queue id="test_queue_confirm" name="test_queue_confirm"/>

<rabbit:direct-exchange name="test_exchange_confirm">
    <rabbit:bindings>
        <rabbit:binding queue="test_queue_confirm" key="confirm"/>
    </rabbit:bindings>
</rabbit:direct-exchange>

/*在ProducerTest测试类中定义回调*/
@Test
public void testConfirm(){
    rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            System.out.println("执行confirm方法......");
            //ack表示发送成功或者失败(比如该交换机不存在)
            if(ack){
                System.out.println("接收成功"+cause);
            }else {
                System.out.println("接收失败"+cause);
            }
        }
    });
    //发送消息
    rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","message_confirm");
}


@Test
public void testReturn(){
    //设置交换机处理失败消息的模式(如果消息没有路由到Queue 默认是丢弃消息)
    rabbitTemplate.setMandatory(true);
    //设置ReturnCallBack
    rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
            System.out.println("return 执行了.....");
        }
    });
   //发送消息(故意写错路由key)
   rabbitTemplate.convertAndSend("test_exchange_confirm","confirm111","message_confirm");
}

小结

  1. 在connectionFactory中开启确认模式和回退模式
  2. 在rabbitTemplate中设置两个回调函数(注意!消息回退还要设置交换机处理失败消息的模式,rabbitTemplate.setMandatory(true),不然默认是丢弃消息)

Consumer Ack

简介:acknowledge,表示消费端确认收到消息。

三种签收方式:none(自动),manual(手动),auto(根据情况)

/*spring-rabbitmq-consumer.xml*/

<context:component-scan base-package="com.lxw.listener"/>

<!--定义监听器容器-->
<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual">
    <rabbit:listener ref="ackListener" queue-names="test_queue_confirm"/>
</rabbit:listener-container>

/**
 * ack机制
 * 1.设置手动签收 (acknowledge="manual")
 * 2.让监听器类实现ChannelAwareMessageListener接口
 * 3.如果消息成功处理则调用channel的basicAck签收
 * 4.如果消息处理失败则调用channel的basicNack拒绝签收,让broker重新发送消息给consumer
 */
@Component
public class AckListener implements ChannelAwareMessageListener {
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            //接收消息
            System.out.println(new String(message.getBody()));
            //处理业务逻辑
            System.out.println("处理业务逻辑......");
            //channel手动签收
            channel.basicAck(deliveryTag,true);
        } catch (IOException e) {
            e.printStackTrace();
            //拒绝签收
            channel.basicNack(deliveryTag,true,true);
        }
    }
}

PS:

  1. deliveryTag :消息的index
  2. multiple:是否批量处理 如果为true 就一次性签收所有小于deliveryTag的消息
  3. requeue:是否重回队列 如果设置为true 那么broker会重新发送消息给消费端
  4. broker:也是rabbitmq server 可以理解为介于生产者和消费者之间的服务器

消费端限流

@Component
public class QosListener implements ChannelAwareMessageListener {
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        //为了更好的看到效果
        Thread.sleep(1000);
        //获取消息
        System.out.println(new String(message.getBody()));
        //处理业务逻辑
        System.out.println("处理业务逻辑");
        //签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
    }
}

小结

  1. 确保ack机制为手动确认
  2. 在监听器容器中配置属性(prefetch =n 表示每次从MQ拉取n条消息 直到确认消息消费完毕 才会继续拉去下一条消息)

TTL

简介:ttl指的是存活时间/过期时间,如果过了这个时间消息就过期。(不仅可以对消息设置过期时间,也可以对队列设置)

//声明队列、交换机并且绑定
<rabbit:queue name="test_queue_ttl" id="test_queue_ttl">
    <!--设置queue的参数 队列的过期时间 记得声明类型-->
    <rabbit:queue-arguments>
        <entry key="x-message-ttl" value="100000" value-type="java.lang.Integer"></entry>
    </rabbit:queue-arguments>
</rabbit:queue>

<rabbit:topic-exchange name="test_exchange_ttl">
    <rabbit:bindings>
        <rabbit:binding pattern="ttl.#" queue="test_queue_ttl"/>
    </rabbit:bindings>
</rabbit:topic-exchange>


/*消息单独过期*/
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        //设置message信息(设置消息过期时间)
        message.getMessageProperties().setExpiration("5000");
        return message;
    }
};
rabbitTemplate.convertAndSend("test_exchange_ttl","ttl.message","message ttl",messagePostProcessor);


//ps:这里有一个细节 要注意一下
for (int i = 0; i < 10; i++) {
    //i等于5发送过期消息 不等于5发送不过期的消息
    //发现消息并不会消失 (**证明只有消息在队列头部---要被消费时候才会单独判断是否达到过期时间**)
    if(i==5){
        rabbitTemplate.convertAndSend("test_exchange_ttl","ttl.message","message ttl",messagePostProcessor);
    }else {
        rabbitTemplate.convertAndSend("test_exchange_ttl","ttl.message","message ttl");
    }
}

小结

  1. 队列统一过期(队列参数里面设置x-message-ttl)
  2. 消息单独过期(new一个消息后处理对象messagePostProcessor,setExpiration(“1000”)之后convertAndSend发送消息的时候,将这个后处理对象作为参数传进去)
  3. 消息的单独过期是当消息处于队列的顶端要被消费了才开始倒计时过期,如果不在顶端那么消息是不会过期的,所以一般设置TTL都是针对整个队列。

死信队列

简介:当消息死亡的时候,可以被重新发送到另一个交换机DLX

//普通队列里面 参数绑定死信队列的交换机
<rabbit:queue name="test_queue_dlx" id="test_queue_dlx">
    <rabbit:queue-arguments>
        <entry key="x-dead-letter-exchange" value="exchange_dlx"/>
        <entry key="x-dead-letter-routing-key" value="dlx.#"/>
        <!--设置队列的过期时间ttl以及长度限制-->
        <entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"/>
        <entry key="x-max-length" value="5" value-type="java.lang.Integer"/>
    </rabbit:queue-arguments>
</rabbit:queue>

//整一个DlxListener消费者用来测试消息拒收(加入listener-container监听容器中)
@Component
public class DlxListener implements ChannelAwareMessageListener {
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println(new String(message.getBody()));
            System.out.println("处理业务逻辑......");
            int i = 4/0;//制造一个错误
            channel.basicAck(deliveryTag,false);
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("出现错误,拒绝接受!");
            //拒绝签收 
            channel.basicNack(deliveryTag,true,false);
        }
    }
}

/**
 * 发送测试死信消息:
 * 1.过期时间
 * 2.长度限制
 * 3.消息拒收
 */
@Test
public void testDlx(){
    rabbitTemplate.convertAndSend("test_exchange_dlx", "test.dlx.hhh", "I am a message!");

       for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("test_exchange_dlx", "test.dlx.hhh", "I am a message!");
       }

    rabbitTemplate.convertAndSend("test_exchange_dlx", "test.dlx.hhh", "I am a message!");
}

小结

  • 死信交换机和死信队列和普通的队列交换机没啥区别

  • 记得拒绝签收的时候设置参数requeue =false,如果重回队列的话就不会发到死信队列里面去了

  • 消息成为死信的情况:

    1. 消息过期
    2. 队列消息长度达到限制(这个长度指消息一共有几条
    3. 消费者拒收消息,且不返回队列

延迟队列

简介:延迟队列,消息进入队列后不会被立即消费,只有达到指定时间后才会被消费。(下单后,一定时间内没有支付,就取消订单,回滚库存。或者用户注册一段时间后,发送消息)

这里要提一嘴,RabbitMQ中并未提供延迟队列功能,所以我们要TTL+死信队列 组合实现延迟队列。


总结

RabbitMQ中不乏其他高级特性,如日志监控、消息追踪以及一些应用中的问题,如消息补偿、幂等性保障,集群搭建等等。目前仅仅是简单了解下,以后做到了具体应用再详细补充。


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
WordPress博客SEO自媒体资讯主题模板RabbitV2.0 Rabbitv2.0主题为SEO而生,是一款专注于SEO优化用途的WordPress主题,专为博客、自媒体、资讯类等类型网站SEO优化设计开发,自适应兼容手机、平板设备,支持前端用户中心,可以前端发布/投稿文章,同时主题支持专题功能,可以添加文章专题。 功能介绍 添加站外链接自动添加nofollow属性并新窗口打开功能,更符合SEO规则; 美化GO跳转页面,用户体验提供升; 添加了GO跳转功能,更符合SEO规则; 首页全屏轮播图,用户体验提供升; 首页上下滚动广告,用户体验提供升; 首页随机广告,用户体验提供升; 列表置顶轮播图,用户体验提供升; 文章左右翻页,用户体验提供升; 首页轮播样式优化,用户体验提供升; 优化标签列表页,更符合SEO规则; 优化标签显示,色彩化用户体验提供升; 文章页增加复制弹窗提示,防止内容被恶意盗取; 首页滚动公告,用户体验提供升; 去除分类category,更符合SEO规则; 彻底禁止WordPress缩略图,节省空间承载; 增加编辑器插入短代码功能,用户体验提供升; 增加公众号吸粉功能,关注访问隐藏内容; 增加文章密码保护功能,用户体验提供升; 增加展开/收缩功能,用户体验提供升; 增加回复可见功能,用户体验提供升; 读者墙,展示用户与读者信息; 禁用古腾堡编辑器,优化编辑体验; 以下为原生自带功能(原生版) 响应式设计,兼容手机和平板等移动设备; 自主研发的前端用户中心; 第三方社交帐号登录(可支持微博、QQ、微信登录); 支持手机注册功能; 支持全新高级菜单功能; 文章投稿、发布功能; 文章专题功能; 文章版权设置,可添加多种版权模板,文章可选择适用的模板; 文章打赏、点赞、收藏、分享、阅读模式功能; 当前文章作者信息小工具; 首页幻灯片轮播、头条推荐内容设置; 自主开发Themer框架,支持后台自定义面板设置; 支持腾讯防水墙和阿里云人机验证安全验证; webp支持,可配合第三方云储存/CDN自动切换; 支持标签归档; 支持兔讯功能; 支持百度熊掌号; 缩略图片延迟加载(lazyload),提高页面加载速度; 手机端底部固定浮动栏,可添加拨号联系等选项; 自动获取文章首张图片作为缩略图; 边栏滚动到底部后固定位置功能; 微信分享显示描述、缩略图功能; 支持手机分享图片生成功能; 支持WooCommerce插件,可实现商城功能; 支持文章分页功能; 支持文章图片无alt信息自动使用标题补全功能; 支持文章发布时远程图片保存功能; 广告位设置,可区分移动端,支持文章列表信息流广告位; 中文文件名上传自动重命名,避免图片无法打开的情况; 主题颜色风格自定义设置,可以随意设置网站配色风格; 强大的SEO优化功能,可自定义也可自动获取; 文章标签、关键词自动内链功能; 融入FontAwesome字体图标库,支持多达600+个字体图标; 自带多种小工具(持续增加中); 文章页面相关文章展示; 支持首页合作伙伴、友情链接显示; 支持在线客服/微信二维码/分享/返回顶部悬浮层; 支持自定义CSS样式设置; 支持谷歌字体链接和头像链接替换,加快网站打开速度; 缩略图自动智能裁剪功能; 无限页面边栏添加; 三级下拉菜单支持; 文章评论功能(可选择开启或关闭); 内置多个文章列表模板,可供分类、标签和专题页选择; 内置多个页面模板可供选择; 支持文章段落缩进设置; 基于Bootstrap前端框架(bootstrap介绍)开发; 文章组件添加功能(基于shortcode开发); 兼容IE9+、Chrome、Firefox、Safari、360等主流浏览器,针对Mac OS X等Retina屏幕优化显示; 浏览器兼容提示,针对低版本IE浏览器会显示升级提示; 针对响应式网站的移动端SEO优化; HTTPS优化,全面支持HTTPS网站;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值