【问题标题】:Apache camel,RabbitMQ how to send messages/objectsApache骆驼,RabbitMQ如何发送消息/对象
【发布时间】:2014-12-15 05:20:53
【问题描述】:

我希望有人可以在这个问题上提供一些帮助。

我正在使用骆驼rabbitmq,出于测试目的,我试图向队列发送一条消息,我试图在rabbitmq界面中显示该消息,然后将其读回。

但是我不能让它工作。

我认为可行的是,我在 rabbitmq 管理界面的交换选项卡中创建了一个新的交换。 在我的 java 代码中,我将消息发送到该交换。执行代码时,我可以在 Web 界面中看到一个峰值,表明已收到某些内容,但我看不到已收到的内容。 当我尝试阅读时,我无法阅读并收到以下错误:

有人可以提供一个关于如何发送消息、在网络界面中查看并阅读的实际示例吗?任何显示此过程的教程也将不胜感激。

谢谢

================= 第二部分

我现在遇到的错误如下:

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; reason: {#method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - cannot redeclare exchange 'rhSearchExchange' in vhost '/' with different type, durable, internal or autodelete value, class-id=40, method-id=10), null, ""}
    at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
    at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
    at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
    at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
    at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)
    ... 47 more

我有以下设置:

我收到此错误,我认为我的 URI 有问题,我必须定义一些我缺少的额外参数 我的交换是直接类型的 我的队列是持久型 我的 uri 是: rabbitmq://192.168.59.105:5672/rhSearchExchange?username=guest&password=guest&routingKey=rhSearchQueue

对此有何意见?

谢谢

【问题讨论】:

  • 对此有何建议?
  • 我一直在寻找类似的教程...我可以将消息发布到交易所,但我不能从骆驼中消费它们。但是,对于您的错误,我认为问题在于您没有将消息路由到任何地方。例如,我相信您的配置是 from("rabbitmq:localhost..."); 但它应该是 from("rabbitmq:localhost:...").to("foo:bar") foo:bar 可能类似于 mock:result
  • 感谢您的回复。我知道我必须使用“to”来流式传输/保存它。我已经更新了我的线程以显示我现在遇到的错误。如果有人对如何解决这个问题有任何建议。
  • 请从第二部分开始阅读,因为这是我现在遇到的错误

标签: java spring apache-camel rabbitmq


【解决方案1】:

所以我昨天能够解决这个问题,我遇到了与您相同(或至少相似)的问题。

您在 RabbitMQ URI 中的选项必须与创建交换时使用的选项完全匹配。例如,在我的配置中,我有一个名为 tasks 的交换器,它是直接类型,是持久的,并且没有配置为自动删除。请注意,rabbitmq 骆驼组件中自动删除选项的默认值为true。另外,我想用路由键camel 获取消息。这意味着我的 rabbitmq URI 需要看起来像:

rabbitmq:localhost:5672/tasks?username=guest&password=guest&autoDelete=false&routingKey=camel

另外,我想从一个名为task_queue 的现有队列中读取数据,而不是让rabbitmq camel 组件声明它自己的队列。因此,我还需要添加一个额外的查询参数,所以我的 rabbitmq URI 是

rabbitmq:localhost:5672/tasks?username=guest&password=guest&autoDelete=false&routingKey=camel&queue=task_queue

此配置对我有用。下面,我从配置交换和队列并发送消息的代码中添加了一些 Java 代码 sn-ps,以及我的 Camel Route 配置。

交换和队列配置:

rabbitConnFactory = new ConnectionFactory();
rabbitConnFactory.setHost("localhost");
final Connection conn = rabbitConnFactory.newConnection();
final Channel channel = conn.createChannel();

// declare a direct, durable, non autodelete exchange named 'tasks'    
channel.exchangeDeclare("tasks", "direct", true); 
// declare a durable, non exclusive, non autodelete queue named 'task_queue'
channel.queueDeclare("task_queue", true, false, false, null); 
// bind 'task_queue' to the 'tasks' exchange with the routing key 'camel'
channel.queueBind("task_queue", "tasks", "camel"); 

发送消息:

channel.basicPublish("tasks", "camel", MessageProperties.PERSISTENT_TEXT_PLAIN, "hello, world!".getBytes());

骆驼路线:

@Override
public void configure() throws Exception {
    from("rabbitmq:localhost:5672/tasks?username=guest&password=guest&autoDelete=false&routingKey=camel&queue=task_queue")
        .to("mock:result");
}

我希望这会有所帮助!

【讨论】:

  • 非常感谢 llawj,它成功了。我添加了 autoDelete=false 以及队列的名称以及之前已经存在的 routingkey。所以基本上这是获得正确的uri的问题。我遇到的一个问题是,当它读取队列时,它会读取其中的所有消息?我试图在 uri 中设置 prefetchEnabled=true 和 prefetchCount=1 但这会出错。关于如何只提取一条消息的任何建议?谢谢
  • 说实话,我不太确定。我刚刚开始使用 Camel / RabbitMQ,我不需要限制我正在阅读的消息数量。
  • 我会检查是否能找到办法。感谢您的帮助。
  • 看起来从 Camel 2.14 开始,不需要执行手动交换、队列和绑定声明。请看camel.apache.org/rabbitmq.html 有'declare' 选项,默认为true
  • @cpu2007 你看到的错误是什么?除了 prefetchCount=1 之外,您还尝试过 autoAck=false 吗?这样,在您为正在处理的消息发送 ack 之前,代理不会提供更多消息
【解决方案2】:

因为它是 Google 上最热门的 rabbitmq/camel 集成,所以我觉得有必要为这个主题添加更多内容。 简单骆驼示例的缺乏令我惊讶。

import org.apache.camel.CamelContext;
import org.apache.camel.ConsumerTemplate;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultCamelContext;
import org.junit.Test;

public class CamelTests {
    CamelContext context;
    ProducerTemplate producer;
    ConsumerTemplate consumer;
    Endpoint endpoint;

    @Test
    public void camelRabbitMq() throws Exception {
        context = new DefaultCamelContext();

        context.start();

        endpoint = context.getEndpoint("rabbitmq://192.168.56.11:5672/tasks?username=benchmark&password=benchmark&autoDelete=false&routingKey=camel&queue=task_queue");

        producer = context.createProducerTemplate();

        producer.setDefaultEndpoint(endpoint);
        producer.sendBody("one");
        producer.sendBody("two");
        producer.sendBody("three");
        producer.sendBody("four");
        producer.sendBody("done");

        consumer = context.createConsumerTemplate();
        String body = null;
        while (!"done".equals(body)) {
            Exchange receive = consumer.receive(endpoint);
            body = receive.getIn().getBody(String.class);
            System.out.println(body);
        }

        context.stop();

    }

}

【讨论】:

  • 来自Producer-/ConsumerTemplates' JavaDoc:„重要提示: 请务必致电org.apache.camel.ProducerTemplate.stop() | ConsumerTemplate.stop() 使用完模板后,清理所有资源。“
猜你喜欢
  • 2016-12-08
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 2013-08-10
  • 2013-01-24
  • 1970-01-01
相关资源
最近更新 更多