ActiveMQ的可靠性

ActiveMQ的可靠性

控制消息签收(Acknowledgment)

客户端成功接收一条消息的标志是这条消息被签售。成功签收一条消息一般包括如下三个阶段:

  1. 客户端接收消息;
  2. 客户端处理消息;
  3. 消息被签收。签收可以由ActiveMQ发起,也可以由客户端发起,取决于Session签收模式的设置。
  • 指定消息传送模式

    详见ActiveMQ消息传送机制-设置方式

  • 签收模式的设置

    再带事务的Session中,签收自动发生在事务提交时,如果不提交事务,在系统重启后消息会再次发送。如果事务回滚,所有已经连接的消息将会被再次传送。在不带事务的Session中,一条消息何时和如何被签收取决于Session的设置。

    1. Session.AUTO_ACKNOWLEDGE

      自动确认,客户端发送和接收消息不需要做额外的工作。 当客户端从receive或OnMessage成功返回时,Session自动签收客户端的这条消息的收条。在AUTO_ACKNOEWLEDGE的Session中,同步接收reveive是上述三个阶段的一个例外,在这中情况下,收条和签收紧随在处理消息之后发生。

    2. Session.CLIENT_ACKNOWLEDGE

      客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。 客户端通过调用消息的acknowledge方法签收消息。在Session层面:签收一个以消费的收条会自动地签收这个Session所有已消费消息的收条。

    3. Session.DUPS_OK_ACKNOWLEDGE

      此选项只是Session不必确保对传送消息的签收,消息可能会重复发送。它可能引起消息的重复,但是降低了Session的开销,所以只有客户端能容忍重复的消息,才可以使用(如果ActiveMQ再次传送同一消息,那么消息头中的JMSRedelivered将设置为true,客户端据此可进行消息的重复处理控制,在需要考虑资源使用时,这种模式非常有效)。

  • 设置签收模式

    Session session=connection.createSession(paramA,paramB);

    paramA是设置事务的,为true时:paramB的值忽略, acknowledgment mode被jms服务器设置为SESSION_TRANSACTED 。

    paramA设置为false时:paramB的值可为Session.AUTO_ACKNOWLEDGE,Session.CLIENT_ACKNOWLEDGE,DUPS_OK_ACKNOWLEDGE其中一个。

  • 持久化订阅

    消息的两种模式,点对点(queue)和发布/订阅(topic),queue模式下,消息是会被持久化到磁盘,而topic模式下,消息会随着服务的停止而消失,但是某些场景下,我们想将topic消息也进行持久化,只需要进行如下改动。

    生产者端:只需要将目的地创建成Topic模式即可,其他不用变 session.createTopic(“xxxx”);

    消费者端:需要为连接指定一个ID,创建持久订阅的目的地和消费者

    			ConnectionFactory factory = new ActiveMQConnectionFactory(USERNAME,PASSWORD,BROKER_URL);
    			Connection conn = factory.createConnection();
    			//需要一个ID
    			conn.setClientID("TopicConsumerTwo");
    			conn.start();
    			//不启用事务,自动应答
    			Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
    			//创建目的地,这里如果想使用持久订阅,创建topic模式的目的地
    			Topic destination = session.createTopic("persistent-topic");
    			//创建消费者-持久订阅的消费者
    			TopicSubscriber topicSubscriber = session.createDurableSubscriber(destination, "any-name");
    			topicSubscriber.setMessageListener(new MessageListener() {
    				@Override
    				public void onMessage(Message message) {
    					try {
    						String msg = ((TextMessage)message).getText();
    						System.out.println("接收消息:"+msg);
    					} catch (JMSException e) {
    						e.printStackTrace();
    					}
    				}
    
  • 双向应答

    双向应答可以这样描述:

    1. producer–>发送消息到broker, 然后等待确认消息
    2. customer–>从broker 获得消息,然后发送确认消息—>broker
    3. producer --> 从broker 获得确认消息

    生产者代码:

    			// 承接刚才的代码,发送消息的时候,需要填写一个回执的地址  
          Destination recall_destination = session.createQueue("recall_queue");  
          // 将回执地址写在消息里面,方便李四知道  
          message.setJMSReplyTo(recall_destination);  
          producer.send(message);   
             
          // 发送之后,某个地方这里变成消息消费者,等待那边给我发送确认消息  
          MessageConsumer replyConsumer =session.createConsumer(recall_destination);  
           // 这里我们用个消息监听  
           // 异步接收
           replyConsumer.setMessageListener(new MessageListener() {  
               @Override  
               public void onMessage(Message message) {  
                   TextMessage textMessage = (TextMessage) message;  
                   try {  
                       System.out.println(textMessage.getText());  
                   } catch (JMSException e) {  
                       e.printStackTrace();  
                   }  
               }  
           });
           // 同步接收
           replyConsumer.receive();
    

    消费者代码:

    				// 获得回执地址  
            Destination recall_destination = message.getJMSReplyTo();  
            // 创建回执消息  
            TextMessage textMessage = session.createTextMessage("张三,我已经收到消息了");  
            // 以上收到消息之后,从新创建生产者,然后在回执过去  
            MessageProducer producer = session.createProducer(recall_destination);  
            producer.send(textMessage);  
    
  • JmsTemplete实现双向应答

发送

    public void sendMessage(String str) throws JMSException {
        TextMessage replyMessage = (TextMessage) jmsTemplate.sendAndReceive(queue, session -> {
            Message message = session.createTextMessage(str);
            message.setJMSReplyTo(replyQueue);
            return message;
        });
        System.out.println(replyMessage.getText());
    }

接收

    public void receiveMessage() throws JMSException {
        TextMessage message = (TextMessage) jmsTemplate.receive(queue);
        System.out.println(message.getText());
        Destination destination = message.getJMSReplyTo();
        jmsTemplate.send(destination, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                Message message=session.createTextMessage("应答消息");
                return message;
            }
        });
  • 消息头的设置

  1. JMSDestination:消息发送的目的地:主要是指Queue和Topic,自动分配
  2. JMSDeliveryMode:传送模式。有两种 :持久模式和非持久模式(persistent或nonpersistent)。前者表示消息在被消费之前,如果JMS提供者DOWN了,重新启动后消息仍然存在。后者在这种情况下表示消息会被丢失。可以通过下面的方式设置:
    Producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
  3. JMSExpiration:表示一个消息的有效期,只有点对点模式中可设置。只有在这个有效期内,消息消费者才可以消费这个消息。默认值为0,表示消息永不过期。可以通过下面的方式设置:
    producer.setTimeToLive(3600000); //有效期1小时 (1000毫秒 * 60秒 * 60分)
  4. JMSPriority:消息优先级,从 0-9 十个级别,0-4 是普通消息,5-9 是加急消息。JMS 不要求JMS Provider 严格按照这十个优先级发送消息,但必须保证加急消息要先于普通消息到达。默认是4级。自动分配
  5. JMSMessageID:一个字符串用来唯一标示一个消息,J主要是用来关联多个Message,例如需要回复一个消息的时候,通常把回复的消息的JMSCorrelationID设置为原来消息的ID。
  6. JMSTimestamp:一个JMS Provider在调用send()方法时自动设置的。它是消息被发送和消费者实际接收的时间差。自动分配
  7. JMSCorrelationID:用来连接到另外一个消息,典型的应用是在回复消息中连接到原消息。在大多数情况下,JMSCorrelationID用于将一条消息标记为对JMSMessageID标示的上一条消息的应答,不过,JMSCorrelationID可以是任何值,不仅仅是JMSMessageID。由开发者设置session.createConsumer(queue,“JMSCorrelationID=’” + message.getJMSMessageID() + “’”);
  8. JMSReplyTo:有时消息生产者希望消费者回复一个消息,JMSReplyTo为一个Destination,表示需要回复的目的地。当然消费者可以不理会它。
  9. JMSType:表示消息体的结构,和JMS提供者有关。
  10. JMSRedelivered:如果一个客户端收到一个设置了JMSRedelivered属性为true的消息,则表示可能客户端曾经在早些时候收到过该消息,但并没有签收(acknowledged)。如果该消息被重新传送,JMSRedelivered=true反之,JMSRedelivered =false。自动设置
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值