【问题标题】:ActiveMQ Dead Letter Queue isn't created未创建 ActiveMQ 死信队列
【发布时间】:2015-04-21 04:14:02
【问题描述】:

我正在尝试使用配置和测试 ActiveMQ 死信队列,但我遇到了一些问题。正如官方文档所说:

当消息在 Active MQ 代理上过期时(它们超出了它们的 生存时间,如果设置)或无法重新交付,它们将被移至 死信队列,因此它们可以被一个 管理员稍后。消息通常重新传递到 以下场景中的客户端:

  1. 客户端正在使用事务 并在会话上调用 rollback()。
  2. 客户端正在使用事务 并在调用提交之前关闭。
  3. 客户端正在使用 会话上的 CLIENT_ACKNOWLEDGE 并在该会话上调用 recover()。

所以,我创建了我的 Producer 类来创建事务会话并在发送消息后回滚事务。正如我所料,消息没有出现在目标队列中,但问题是根本没有创建 DLQ。如何管理死信队列?我使用 JConsole 找不到它 - 只有目标队列,但没有 DLQ。

你知道麻烦在哪里吗?有Producer.java和Spring config!

<bean id="producer" class="com.jmsexamples.Producer">
    <property name="connectionFactory" ref="jmsFactory" />
    <property name="destination" ref="queue" />
    <property name="login" value="roman" />
    <property name="password" value="sawawluha" />
</bean>

<bean id="consumer" class="com.jmsexamples.Consumer">
    <property name="connectionFactory" ref="jmsFactory" />
    <property name="destination" ref="queue" />
    <property name="login" value="roman" />
    <property name="password" value="sawawluha" />
</bean>

<bean id="jdbc_ds" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
        value="jdbc:mysql://localhost:3306/ActiveMQ?relaxAutoCommit=true" />
    <property name="username" value="root" />
    <property name="password" value="" />
    <property name="poolPreparedStatements" value="true" />
</bean>

<amq:connectionFactory id="jmsFactory" brokerURL="tcp://localhost:6616" />

<amq:queue id="queue" physicalName="message.queue" />


<amq:broker id="msgBroker" persistent="true">
    <amq:persistenceAdapter>
        <amq:kahaDB directory="target/activemq-data/kahadb"
            journalMaxFileLength="16mb" />
    </amq:persistenceAdapter>

    <amq:plugins>
        <amq:loggingBrokerPlugin logAll="true" />
    </amq:plugins>


    <amq:destinationPolicy>
        <amq:policyMap>
            <amq:policyEntries>
                <amq:policyEntry queue=">">
                    <amq:deadLetterStrategy>
                        <amq:individualDeadLetterStrategy
                            queuePrefix="DLQ." useQueueForQueueMessages="true"
                            processNonPersistent="true" />
                    </amq:deadLetterStrategy>
                </amq:policyEntry>
            </amq:policyEntries>
        </amq:policyMap>
    </amq:destinationPolicy>

    <amq:transportConnectors>
        <amq:transportConnector name="openwire"
            uri="tcp://localhost:6616" />
    </amq:transportConnectors>
</amq:broker>

制作人:

public class Producer {

    private String login;
    private String password;

    private ConnectionFactory connectionFactory;

    private Destination destination;

    public void setConnectionFactory(ConnectionFactory conFact) {
        this.connectionFactory = conFact;
    }

    public void setDestination(Destination dest) {
        this.destination = dest;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void sendMessage(int count) {

        Connection connection = null;
        Session session = null;

        try {
            System.out.println("Loggining as " + login);

            // it's not neccessary to set login and password in this example
            // but when you are running a normal message server, you should use
            // login and password for authentification
            connection = connectionFactory.createConnection(this.login,
                    this.password); // estabilishing connection
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); // starting
                                                                                // session
            MessageProducer producer = session.createProducer(destination); // initializing
                                                                            // of
                                                                            // message
                                                                            // producer
            System.out.println("Client_acknowledge " + session.getTransacted());
            for (int i = 0; i < count; i++) {
                TextMessage message = session.createTextMessage();

                message.setText("This is text message!");
                producer.send(message);
                System.out.println("message sent #" + i);
                session.rollback();
            }

        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            try {
                session.commit();
                session.close();
                connection.close();
                System.out.println("successfull");

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

感谢您的帮助!

【问题讨论】:

    标签: java spring activemq


    【解决方案1】:

    从生产者方面 - 如果会话回滚,消息将不会在 DLQ 中结束。

    DLQ 的重点是在不丢失任何数据的情况下为有问题的消息提供“出路”。生产者应该知道要发送什么。如果发送事务回滚,则消息不应到达代理。事务消费者将确保“毒消息”最终出现在 DLQ 上,因此它不会阻止进一步的传入消息。

    在正常情况下,生产者上的事务实际上并没有做太多事情。如果您想在给定时刻产生一组消息,您可以在事务中产生“全有或全无”行为。

    【讨论】:

      【解决方案2】:

      回滚的 TX 中的生产者发送的消息不会被发送到死信队列。这些类型的消息被认为从未发布过,因此它们不是 DLQ'ing 的候选者。由于您的客户已决定回滚 TX 那些消息,因此由您的客户来做一些事情。

      【讨论】:

        猜你喜欢
        • 2021-10-07
        • 1970-01-01
        • 2015-01-14
        • 2012-12-10
        • 1970-01-01
        • 1970-01-01
        • 2011-03-15
        • 2018-10-28
        • 1970-01-01
        相关资源
        最近更新 更多