消息队列发布端性能优化

消息发布的性能权衡

AMQP规范提供消息发布中的事务以及消息持久化选项,以提供比自身普通消息发布更高级别的可靠消息通信机制。
这种可靠消息通信机制,包含投递确认功能。
投递确认:该功能提供了不同级别的消息可靠投递机制,包括跨越多个服务器的高可用性队列。

rabbitmq的保障机制(要根据业务进行选择,越往下性能越差)
https://www.jianshu.com/p/cc3d2017e7b3

失败通知

将 mandatory设置为true,如果消息不可路由那么rabbitmq会把完整的消息退回到发布者中

public RabbitTemplate rabbitTemplate(){
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    template.setMandatory(true); //设置发送消息失败重试
    return template;
    }

发布者确认

发布者确认,即Confirm机制具体的实现方式:
1. 普通的java方法:https://blog.csdn.net/vbirdbest/article/details/78699913
2. 结合springboot的实现方法

第一步:spring.rabbitmq.template.mandatory = true 设置成true
第二步:spring.rabbitmq.publisher-confirms = true 设置成true
第三步:编写一个 java 类,实现 RabbitTemplate.ConfirmCallback 接口,在这个里面我们可以确认消息是否到达了RabbitMQ服务器。

这里RabbitMq提供一个回调函数可以将投递失败的消息给输出出来

// 消息是否从Exchange路由到Queue, 注意: 这是一个失败回调, 只有消息从Exchange路由到Queue失败才会回调这个方法
  rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
         log.info("消息从Exchange路由到Queue失败: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, message);
    });

消费者确认

开启ack应答模式,作为事务的轻量级替代方法
这种应答模式分为:自动应答和手动应答
自动应答: 消RabbitMQ可以从队列中删除该消息了,可以通过显示调用channel.basicAck(envelope.getDeliveryTag(), false);来告诉消息服务器来删除消息费者一收到消息就表示消费者收到了消息,消费者收到了消息就会立即从队列中删除。

手动应答: 当消费者收到消息在合适的时候来显示的进行确认,说我已经接收到了该消息了,RabbitMQ可以从队列中删除该消息了,可以通过显示调用channel.basicAck(envelope.getDeliveryTag(), false);来告诉消息服务器来删除消息
普通的java: https://blog.csdn.net/vbirdbest/article/details/78699913
springboot项目: https://blog.csdn.net/linpeng_1/article/details/80505828

备用交换器

备用交换器用于处理无法路由的消息。备用交换器在第一次声明交换器时被指定,用来提供一种预先存在的交换器,即如果交换器无法路由消息,那么消息就会被路由到这个新的备用交换器。

死信交换器:
过期的消息、basic.nack或basic.reject且requeue参数为false或队列满的消息将进入此交换器

springboot整合rabbitmq实现生产者消息确认、死信交换器、备用交换器的消息处理
https://www.iteye.com/blog/huan1993-2433263

事务

采用AMQP事务机制和发布者确认的机制,来解决服务器数据丢失的问题。
这种机制极大牺牲了性能从而换取消息的可靠性。
java的实现方式: https://www.cnblogs.com/vipstone/p/9350075.html
springboot的实现方式: https://blog.csdn.net/zhanngle/article/details/86267986

高可用队列

高可用队列又称为HA队列,需要RabbitMQ集群环境,可以通过使用AMQP或者使用基于web的管理界面来设置。
RabbitMQ集群搭建结合Erlang来实现其内部通信,借助Haproxy实现请求的负载均衡。
结合springboot实现消息发送的案例: https://blog.csdn.net/zhuyu19911016520/article/details/80206202

基于事务的高可用队列
在一个集群的环境下,采用的是事务或投递确认机制,则消息在被HA队列定义的所有活动节点确认之后,RabbitMQ才会发送成功的响应。这种方式会造成很大的延迟。

消息持久化

消息持久化是解决消息被投递到RabbitMQ的内存中,还没有投递到消费者实例之前就宕机了,而导致消息丢失的问题。
解决的实例:将Exchange(交换机,存储着消息的路由信息)、queue和message都持久化到硬盘,这样,RabbitMQ重启时会把持久化的Exchange、queue和message从硬盘重新加载出来,
重新投递消息。

交换机的持久化
第二个参数durable: 是否持久化, 第三个参数autoDelete: 当所有绑定队列都不再使用时, 是否自动删除交换器, true: 删除, false: 不删除

@Bean
public DirectExchange logUserExchange() {
    return new DirectExchange("log.user.exchange", true, false);
}

queue的持久化
声明队列时指定持久化参数为true即可

@Bean
public Queue logUserQueue() {
    return new Queue("log.user.queue.name", true);
}

message的持久化
将delivery-mode设置为2,即可以实现message的持久化。
在默认的情况下message都是持久化的。
下面是发送一个不持久化的message

/**
* 推送一个非持久化的消息,这个消息推送到持久化的队列时,mq重启,这个消息会丢失;上面的持久化消息不会丢失
*
* @param ans
* @return
*/private String publish2mq2(String ans) {
    MessageProperties properties = new MessageProperties();
    properties.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
    Message message = rabbitTemplate.getMessageConverter().toMessage("NonDurable = " + ans, properties);
    rabbitTemplate.convertAndSend(MqConstants.exchange, MqConstants.routing, message);
    System.out.println("publish: " + message);
    return message.toString();}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章