我想使用topic
交易所将股价数据发送到Rabbitmq。我的想法是使用以下路由键进行主题交换:
<message-type>.<ticker>
我能够使用本地RabbitMQ cient做到这一点,但是我不知道如何在MassTransit的帮助下做到这一点。
// setup topologies
rabbitCfg.Send<ComMessage>(x =>
{
x.UseRoutingKeyFormatter(context =>
$"quote.{context.Message.Ticker}");
});
rabbitCfg.Message<ComMessage>(x => x.SetEntityName("Quotes"));
rabbitCfg.Publish<ComMessage>(x =>
{
x.ExchangeType = ExchangeType.Topic;
});
// setup reciever
rabbitCfg.ReceiveEndpoint(host, "MSFT", e =>
{
e.Bind("Quotes", c =>
{
c.RoutingKey = "quote.MSFT";
c.ExchangeType = ExchangeType.Topic;
});
e.Consumer<PriceConsumer>();
});
发送消息:
await _bus.Publish(new ComMessage
{
Ticker = "MSFT",
Price = "10"
});
但是,它不起作用。队列未创建,但交换接收消息:
哪里有问题?
答案 0 :(得分:1)
我认为您忘记了一条重要的电话线。作为参考,我提供了使用主题交流的工作单元测试的源代码。
在接收端点中,您需要禁用自动交换绑定。
cfg.ReceiveEndpoint(host, "MSFT", x =>
{
x.BindMessageExchanges = false;
...
}
一个工作示例如下所示:
using System;
using System.Threading.Tasks;
using GreenPipes.Util;
using NUnit.Framework;
using RabbitMQ.Client;
using RoutingKeyTopic;
namespace RoutingKeyTopic
{
public class Message
{
public Message(decimal price, string symbol)
{
Price = price;
Symbol = symbol;
}
public string Symbol { get; set; }
public decimal Price { get; set; }
}
}
[TestFixture]
public class Using_a_routing_key_and_topic_exchange :
RabbitMqTestFixture
{
[Test]
public async Task Should_support_routing_by_key_and_exchange_name()
{
var fooHandle = await Subscribe("MSFT");
try
{
var barHandle = await Subscribe("UBER");
try
{
await Bus.Publish(new Message(100.0m, "MSFT"));
await Bus.Publish(new Message(3.50m, "UBER"));
await Consumer.Microsoft;
await Consumer.Uber;
}
finally
{
await barHandle.StopAsync(TestCancellationToken);
}
}
finally
{
await fooHandle.StopAsync(TestCancellationToken);
}
}
async Task<HostReceiveEndpointHandle> Subscribe(string key)
{
var queueName = $"Stock-{key}";
var handle = Host.ConnectReceiveEndpoint(queueName, x =>
{
x.BindMessageExchanges = false;
x.Consumer<Consumer>();
x.Bind<Message>(e =>
{
e.RoutingKey = GetRoutingKey(key);
e.ExchangeType = ExchangeType.Topic;
});
});
await handle.Ready;
return handle;
}
protected override void ConfigureRabbitMqBusHost(IRabbitMqBusFactoryConfigurator configurator, IRabbitMqHost host)
{
base.ConfigureRabbitMqBusHost(configurator, host);
configurator.Message<Message>(x => x.SetEntityName(ExchangeName));
configurator.Publish<Message>(x => x.ExchangeType = ExchangeType.Topic);
configurator.Send<Message>(x => x.UseRoutingKeyFormatter(context => GetRoutingKey(context.Message.Symbol)));
}
string ExchangeName { get; } = "Quotes";
string GetRoutingKey(string routingKey)
{
return $"quote.{routingKey}";
}
class Consumer :
IConsumer<Message>
{
static readonly TaskCompletionSource<Message> _microsoft = new TaskCompletionSource<Message>();
static readonly TaskCompletionSource<Message> _uber = new TaskCompletionSource<Message>();
public static Task<Message> Microsoft => _microsoft.Task;
public static Task<Message> Uber => _uber.Task;
public Task Consume(ConsumeContext<Message> context)
{
Console.WriteLine($"Received {context.Message.Symbol} for {context.RoutingKey()}");
if (context.Message.Symbol == "MSFT")
_microsoft.TrySetResult(context.Message);
if (context.Message.Symbol == "UBER")
_uber.TrySetResult(context.Message);
return TaskUtil.Completed;
}
}
}