4

当我使用标头交换时使用 Spring AMQP,无论标头内容如何,​​所有消息都会发送到队列。更具体地说,我在 xml 中声明,我只想要标题中带有“betty rubble”的消息,但仍然可以通过不匹配的消息。我究竟做错了什么?我也希望能够以编程方式完成它,所以我也尝试过使用 BindingBuilder 类,但在那里也没有任何乐趣。似乎没有任何与 spring amqp 交换标头的示例或与 BindingBuilder 交换的示例。

我已经成功地使用这些带有 java 和普通 rabbit api 的标头进行路由/过滤,但是 Spring 提供了一些我想使用的优雅包装。

我正在使用 Spring Core 3.2.2.RELEASE、Spring AMQP 1.1.4.RELEASE、RabbitMq 3.0.4,而不是使用 Spring Integration。这是我的测试形式的代码(可能有一天会断言一些东西:-)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test-rabbit.xml" })
public class SpringRabbitTest  {

    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private HeadersExchange headersExchange;
    @Autowired
    private MessageConverter converter;
    @Autowired
    @Qualifier("mymessage.consumer")
    private Queue consumerQ;


    @Test
    public void headersTest() throws InterruptedException  {

            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setHeader("fred", "flintstone"); 
            messageProperties.setHeader("wilma", "flintstone");
            messageProperties.setHeader("barney", "rubble");   

            MyMessage myMessage = new MyMessage("just an example");
            Message message = converter.toMessage(myMessage, messageProperties);

            amqpTemplate.convertAndSend(headersExchange.getName(),"", message);

            Thread.sleep(5000);
    }
}

应用 Ctx

<?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:task="http://www.springframework.org/schema/task" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
        http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.1.xsd" >

    <context:component-scan base-package="uk.co.abc" />

    <rabbit:connection-factory id="connectionFactory" host="localhost" username="guest" password="guest" virtual-host="/" port="5672" />

    <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.JsonMessageConverter"/>

    <rabbit:template connection-factory="connectionFactory" id="amqpTemplate" message-converter="jsonMessageConverter"/>

    <rabbit:admin connection-factory="connectionFactory" />

    <rabbit:queue id="mymessage.consumer" name="mymessage.consumer"/>

    <rabbit:headers-exchange name="headers.mymessage.all" id="headers.mymessage.all" >
        <rabbit:bindings >
            <rabbit:binding queue="mymessage.consumer" key="betty" value="rubble"   /> 
            <!-- <rabbit:binding queue="mymessage.consumer" key="fred" value="flintstone" /> --> 
            <!-- <rabbit:binding queue="mymessage.consumer" key="barney" value="rubble"   /> --> 
        </rabbit:bindings>
    </rabbit:headers-exchange>



    <rabbit:listener-container connection-factory="connectionFactory" message-converter="jsonMessageConverter" error-handler="loggingErrorHandler">
        <rabbit:listener queues="mymessage.consumer" ref="myMessageHandler" method="handleMyMessage" />
    </rabbit:listener-container>


</beans>

消息豆

package uk.co.abc;

public class MyMessage {

    private String message;

    public MyMessage() {
    }


    public MyMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }


    @Override
    public String toString() {
        return "MyMessage [message=" + message + "]";
    }

}

处理程序

package uk.co.abc;                                                                                                                                                                      

import org.apache.commons.logging.Log;                                                                                                                                                  
import org.apache.commons.logging.LogFactory;                                                                                                                                           
import org.springframework.beans.factory.annotation.Qualifier;                                                                                                                          
import org.springframework.stereotype.Component;                                                                                                                                        

@Component                                                                                                                                                                              
@Qualifier("myMessageHandler")                                                                                                                                                          
public class MyMessageHandler {                                                                                                                                                         


    public void handleMyMessage(MyMessage myMessage) {                                                                                                                                  
        System.out.println("Got it! "  + myMessage);                                                                                                                                    
    }                                                                                             }                                                                                           

为了完整起见,pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                                http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <properties>
        <spring.amqp.version>1.1.4.RELEASE</spring.amqp.version>
        <rabbitmq.version>3.0.4</rabbitmq.version>
        <spring.version>3.2.2.RELEASE</spring.version>
        <log4j.version>1.2.16</log4j.version>
        <slf4j.version>1.5.2</slf4j.version>
    </properties>

    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>


    <dependencies>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-amqp</artifactId>
            <version>${spring.amqp.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
            <version>${spring.amqp.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-erlang</artifactId>
            <version>${spring.amqp.version}</version>
        </dependency>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>${rabbitmq.version}</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.12</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-lgpl</artifactId>
            <version>1.9.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <optional>true</optional>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>

</project>                                                                                           

调试日志暗示交换没有设置标头

DEBUG [org.springframework.amqp.rabbit.connection.CachingConnectionFactory] - Creating cached Rabbit Channel from AMQChannel(amqp://guest@127.0.0.1:5672/,1)
DEBUG [org.springframework.amqp.rabbit.core.RabbitTemplate] - Executing callback on RabbitMQ Channel: Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,1)
DEBUG [org.springframework.amqp.rabbit.core.RabbitAdmin] - declaring Exchange 'headers.mymessage.all'
DEBUG [org.springframework.amqp.rabbit.core.RabbitAdmin] - declaring Queue 'mymessage.consumer'
DEBUG [org.springframework.amqp.rabbit.core.RabbitAdmin] - Binding destination [mymessage.consumer (QUEUE)] to exchange [headers.mymessage.all] with routing key []
DEBUG [org.springframework.amqp.rabbit.core.RabbitAdmin] - Declarations finished
DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] - Started on queue 'mymessage.consumer': Consumer: tag=[null], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,1), acknowledgeMode=AUTO local queue size=0
DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] - Retrieving delivery for Consumer: tag=[null], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,1), acknowledgeMode=AUTO local queue size=0
DEBUG [org.springframework.amqp.rabbit.connection.CachingConnectionFactory] - Creating cached Rabbit Channel from AMQChannel(amqp://guest@127.0.0.1:5672/,2)
DEBUG [org.springframework.amqp.rabbit.core.RabbitTemplate] - Executing callback on RabbitMQ Channel: Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,2)
DEBUG [org.springframework.amqp.rabbit.core.RabbitTemplate] - Publishing message on exchange [headers.mymessage.all], routingKey = []
DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] - Storing delivery for Consumer: tag=[amq.ctag-JS6zwiLjp6cGSNbieRTlvw], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,1), acknowledgeMode=AUTO local queue size=0
DEBUG [org.springframework.amqp.rabbit.listener.BlockingQueueConsumer] - Received message: (Body:'{"message":"just an example"}'; ID:null; Content:application/json; Headers:{wilma=flintstone, fred=flintstone, __TypeId__=uk.co.abc.MyMessage, barney=rubble}; Exchange:headers.mymessage.all; RoutingKey:; Reply:null; DeliveryMode:PERSISTENT; DeliveryTag:1)
Got it! MyMessage [message=just an example]                                                                                                                                                                              
4

1 回答 1

0

我强烈建议您不要使用标头路由,与 Topic 和 Pivotal 自己说不使用它相比,它的性能非常糟糕。

http://techblog.betgenius.com/performance-tuning-our-rabbitmq-routing-strategy/

于 2015-04-27T10:50:32.470 回答