服务器重启后,在主题中保留消息

时间:2015-10-15 10:42:19

标签: java jms activemq spring-integration

我正在学习Spring Integration JMS。我遇到了一个问题,即我的主题不会持续等待客户尚未使用的待处理邮件。

基本上我启动ActiveMQ然后使用REST客户端我正在调用生产者发送消息50次,以便50个消息在主题中排队。在消费者端,我已经应用了5秒的睡眠定时器,以便每个消息以5秒的固定间隔消耗。然后介于两者之间我停止了ActiveMQ。同时,客户端消耗了一些消息,假设已经消耗了50个中的15个。然后,如果我重新启动ActiveMQ,我希望主题能够持续等待35条消息,但我无法在主题选项卡下的管理控制台中看到它。

这是我的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
       xmlns:oxm="http://www.springframework.org/schema/oxm"
       xmlns:int-jme="http://www.springframework.org/schema/integration"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
                http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
                http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">


    <!-- Component scan to find all Spring components -->
    <context:component-scan base-package="com.geekcap.springintegrationexample" />

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="order" value="1" />
        <property name="messageConverters">
            <list>
                <!-- Default converters -->
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
                <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
            </list>
        </property>
    </bean>

    <!-- Define a channel to communicate out to a JMS Destination -->
    <int:channel id="topicChannel"/>

    <!-- Define the ActiveMQ connection factory -->
    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"/>
    </bean>

    <!--
        Define an adaptor that route topicChannel messages to the myTopic topic; the outbound-channel-adapter
        automagically fines the configured connectionFactory bean (by naming convention
      -->
    <int-jms:outbound-channel-adapter channel="topicChannel"
                                      destination-name="topic.myTopic"
                                      pub-sub-domain="true" />

    <!-- Create a channel for a listener that will consume messages-->
    <int:channel id="listenerChannel" />

    <int-jms:message-driven-channel-adapter id="messageDrivenAdapter"
                                            channel="getPayloadChannel"
                                            destination-name="topic.myTopic"
                                            pub-sub-domain="true" />

    <int:service-activator input-channel="listenerChannel" ref="messageListenerImpl" method="processMessage" />

    <int:channel id="getPayloadChannel" />

    <int:service-activator input-channel="getPayloadChannel" output-channel="listenerChannel" ref="retrievePayloadServiceImpl" method="getPayload" />

</beans>

我还读到默认模式是持久的。但就我而言,它似乎没有奏效。

修改

根据Gary Russel在添加属性后给出的答案

  • 订阅的耐用= “真”
  • 耐久订阅的名称= “mySubscription”

<int-jms:message-driven-channel-adapter>我面临与XML相关的问题

  • cvc-complex-type.3.2.2:不允许在'int-jms:message-driven-channel-adapter'元素中出现属性'subscription-durable'。

  • cvc-complex-type.3.2.2:不允许在'int-jms:message-driven-channel-adapter'元素中出现属性'durable-subscription-name'。

    < / LI>

enter image description here

请帮助

2 个答案:

答案 0 :(得分:1)

默认情况下,这就是主题如何工作,读取JMS规范。

主题是发布/订阅;只有在场的订阅者才能收到该消息。

如果你发布5,启动消费者,发布另一个5;他只会得到第二个5。

如果你在获得全部5之前杀死经纪人;在重新启动期间,经纪人看到没有消费者,所以他清除了消息。

您可以通过使用持久订阅来更改此行为,在这种情况下,即使当前未连接,代理也会为每个此类订阅保留消息。

要使用Spring Integration进行配置,请在消息驱动的通道适配器上设置subscription-durable,并为其指定唯一的subscription-name

答案 1 :(得分:0)

Activemq 中的主题不是持久和持久的,因此万一您的消费者之一宕机。你会丢失你的消息。

为了使主题持久和持久,您可以通过为每个消费者创建唯一的客户端 ID 来创建持久消费者。

但同样,如果您遵循微服务架构,这不是分布式的。因此,多个 Pod 或副本会在消费消息时产生问题,因为持久消费者不可能实现负载平衡。

为了缓解这种情况,Activemq 中有一个虚拟主题选项。下面提供了更多详细信息,

您可以在名为 VirtualTopic.MyTopic 的主题中通过您的制作人发送您的消息。 ** 注意:对于默认的 activemq 配置,您必须遵循此命名约定。但是是的,还有一种方法可以覆盖此命名约定。

现在,要通过多个消费者(此处为 A 和 B)使用您的消息,您还必须为您的消费者端目的地设置命名约定,例如。 Consumer.A.VirtualTopic.MyTopic Consumer.B.VirtualTopic.MyTopic 这两个消费者将通过上面创建的主题接收消息,并在相同的多个副本之间启用负载平衡消费者。

我希望这能帮助您解决有关 activemq 主题的问题。