一、客户端消息确认
代码可以参考:https://mp.csdn.net/postedit/89675033
1 自动确认
第二个参数就是自定确认:设置为true就表示自动确认
channel.basicConsume(TASK_QUEUE_NAME, true, deliverCallback, consumerTag -> { });
2 手动确认
手动确认消息ack:默认情况下,手动消息确认已打开。在前面的示例中,我们通过autoAck = true 标志明确地将它们关闭,改为自动确认。 一旦我们完成任务,就应该将此标志设置为false并从工作人员发送正确的确认。
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
multiple第二个参数,true表示确认全部消息 x < deliverytag 的所有消息都会确认,false表示只确认当前这条消息
channel.basicRecover(); 补发 里面有个参数如果是true表示会发给不同的consumer消费者,false表示会发给同一个consumer
basic.ack用于肯定确认
basic.nack用于否定确认(注意:这是AMQP 0-9-1的RabbitMQ扩展) 可以批量拒绝也可以单个
basic.reject用于否定确认,但与basic.nack相比有一个限制
二、发布端确认
影响性能的confirm机制 < tx机制【最耗费性能】
1 confirm机制
开启确认
channel.confirmSelect
执行发布
channel.basicPublish
等待确认是否成功
channel.waitForConfirms
2 tx事务机制 在try catch中
开启
channel.txSelect();
发布
channel.basicPublish
提交
channel.txCommit();
回滚
channel.txRollback();
三、消息持久化
确保消息不会丢失需要做两件事:我们需要将队列和消息都标记为持久。
1需要声明队列是持久的
2现在我们需要将消息标记为持久性 - 通过将MessageProperties(实现BasicProperties)设置为值PERSISTENT_TEXT_PLAIN。channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);//参数{"x-message-ttl", 1000*8 }
String message = String.join(" ", argv);
//此时我们确信即使RabbitMQ重新启动,task_queue队列也不会丢失。现在我们需要将消息标记为持久性 -
// 通过将MessageProperties(实现BasicProperties)设置为值PERSISTENT_TEXT_PLAIN。
//第一个参数是交换的名称。空字符串表示默认或无名交换:消息通过routingKey指定的名称路由到队列(如果存在),routingkey指定名称跟队列名称相同找到是否存在,如果没有找到就可以传递消息到队列
channel.basicPublish("", TASK_QUEUE_NAME,
MessageProperties.PERSISTENT_TEXT_PLAIN, //String expiration 消息过期时间
message.getBytes("UTF-8"));
四、BasicProperties 属性详解
通过将MessageProperties(实现BasicProperties)设置为值PERSISTENT_TEXT_PLAIN。
BasicProperties的几个属性
- content_type
- content_encoding
- priority
- correlation_id
- reply_to
- expiration
- message_id
- timestamp
- type
- user_id
- app_id
- cluster_id
private String contentType; private String contentEncoding; private Map<String,Object> headers; header类型的交换机可以用到 private Integer deliveryMode; 消息持久化 1 不持久化 2 持久化 private Integer priority; 优先级 private String correlationId; 用于将RPC响应与请求相关联 private String replyTo; 通常用于命名回调队列 private String expiration; 设置过期消息过期时间 private String messageId; private Date timestamp; private String type; private String userId; private String appId; private String clusterId;
六、lazy queue
如何定义:就是在定义队列的时候传入arguement参数:map中方的是x-queue-mode:lazy 这样的就定义了懒队列
map.put("x-queue-mode","lazy");
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, map);
Lazy Queue: 数据来了,我就将其放到disk中,而且内存中不存放。(Requested by Consumer )
Default Queue: (in-memory) 数据直接放到内存中。
(on disk) 会将数据放到内存中,同时还会将message放到disk中。等到内存有压力或 gc需要回收内存等等情况,会将memory paged out 到disk中。
可以将Queue插入int.maxvalue条数据。。。看看memory的情况。。。。
1. Lazy Queue + inMemory = 还会将message放到 disk中。 可以看到,只有几M的增长。
2. Default Queue + InMemory = 如果你采用的是inmemory,在内存急缺的情况下还是会paged out 压入磁盘
3. Lazy Queue + Disk = 内存不会涨上去,而且会在restart之后message还会保存
4. Default Queue + Disk = 内存 + 磁盘 都会数据