简体   繁体   English

未创建ActiveMQ死信队列

[英]ActiveMQ Dead Letter Queue isn't created

I'm trying to use configure and test ActiveMQ dead letter queue, but I have some issue. 我正在尝试使用configure和测试ActiveMQ死信队列,但我有一些问题。 As in official docs said: 正如官方文件所说:

When messages expire on the Active MQ broker (they exceed their time-to-live, if set) or can't be redelivered, they're moved to a dead-letter queue, so they can be con- sumed or browsed by an administrator at a later point. 当消息在Active MQ代理上过期(它们超过它们的生存时间,如果设置)或无法重新传递时,它们将被移动到死信队列,因此它们可以被消耗或浏览管理员稍后。 Messages are normally redelivered to a client in the following scenarios: 在以下情况下,通常会将消息重新传递给客户端:

  1. A client is using transactions and calls rollback() on the session. 客户端正在使用事务并在会话上调用rollback()。
  2. A client is using transactions and closes before calling commit. 客户端正在使用事务并在调用commit之前关闭。
  3. A client is using CLIENT_ACKNOWLEDGE on a session and calls recover() on that session. 客户端在会话上使用CLIENT_ACKNOWLEDGE并在该会话上调用recover()。

So, I've made my Producer class to create transactional session and rollback transaction after message is sent. 所以,我已经让我的Producer类在发送消息后创建事务会话和回滚事务。 As I expected, message didn't appear in the destination queue, but trouble is that DLQ wasn't created at all. 正如我所料,消息没有出现在目标队列中,但麻烦的是根本没有创建DLQ。 How can I manage dead letter queue? 我怎样才能管理死信队列? I can't find it using JConsole - there is only destination queue, but not a DLQ. 我无法使用JConsole找到它 - 只有目标队列,但不是DLQ。 在此输入图像描述

Do you know where trouble is? 你知道麻烦在哪里吗? There are Producer.java and Spring config! 有Producer.java和Spring配置!

<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>

Producer: 制片人:

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();
            }

        }
    }
}

Thanks for your help! 谢谢你的帮助!

Messages sent from a producer in a TX that is rolled back will not be sent to the dead letter queue. 从回滚的TX中的生产者发送的消息将不会被发送到死信队列。 These types of messages are considered to have never been published so they are not candidates for DLQ'ing. 这些类型的消息被认为从未发布过,因此它们不是DLQ的候选者。 Since your client has decided to roll back the TX those messages it is up to your client to do something about it. 由于您的客户已决定回滚TX这些消息,因此您的客户需要对其进行一些操作。

From a producer side - the message won't end up in DLQ if the session is rolled back. 从生产者方面 - 如果会话被回滚,消息将不会在DLQ中结束。

The point of DLQ is to have "a way out" with problematic messages without loosing any data. DLQ的目的是在没有丢失任何数据的情况下对有问题的消息进行“解决”。 The producer is supposed to know what to send. 生产者应该知道要发送什么。 If the send transaction is rolled back, the message should never reach the broker. 如果回滚发送事务,则消息永远不会到达代理。 The transactional consumer will make sure a "poison message" ends up on DLQ so it won't block further incoming messages. 事务性消费者将确保DLQ上的“有害消息”结束,因此它不会阻止进一步的传入消息。

In the normal scenario, a transaction on the producer does not really do much. 在正常情况下,生产者的事务并没有真正起作用。 If you want to produce a set of messages at a given moment, you can produce in a transaction to have a "all or nothing" behavior. 如果要在给定时刻生成一组消息,则可以在事务中生成“全部或全部”行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM