EasyNetQ使用(五)【基于主题的路由,控制队列名称】
RabbitMQ
有一个很酷的功能,基于主题的路由,这个功能允许订阅者基于多个条件去过滤消息。一个主题是由点号分隔的单词列表,随消息一同发布。例如:“stock.usd.nyse” 或 “book.uk.london” 或 “a.b.c”,这些可以是任何你喜欢的单词,但通常是一些消息的属性。主题字符串限制最多255
个字符。
去发布一个主题,简单的通过使用带主题参数的Publish
重载方法”
bus.Publish(message,"X.A");
- 1
订阅者能通过指定一个主题去匹配来过滤消息。这些可以包含通配符。
- *(星号)只能匹配一个词。
- (井号)能匹配0到多个词。
这样一个消息被发布带有一个“X.A.2”的主题,将匹配“#”,“X.#”, “.A.”, 但是不能匹配“X.B”或“A”。去订阅一个主题,使用带配置的SubScribe
重载方法。
bus.Subscribe("my_id", handler,
x=>x.WithTopic("X.*"));
警告:带有相同subscriberId
的两个独立订阅,但用了不同主题字符串,可能不会有你预期的效果。一个subscriberId
实际上是去识别一个独立的AMQP
队列。带有相同subscriberId
的两个订阅者将同时连接到同一个队列,同时将添加他们自己主题Binding
。例如,假如你这样做:
bus.Subscribe("my_id",handlerOfXDotStar,
x=>x.WithTopic("X.*"));
bus.Subscribe("my_id",handlerOfStarDotB,
x=>x.WithTopic(*.B));
所以可以匹配“X.”或“.B”的消息都将发送到“XXX_My_id”队列。RabbitMQ
然后轮流在两个消费者之间投递消息。handlerOfXDotStar
和handlerOfStarDotB
会依次轮流得到消息。
现在,如果你想匹配多个主题(”X.”或者“.B”)你可以使用另外一个带多个主题参数的Subscribe重载方法,像下面这样:
bus.Subscribe("my_id",handler,
x=>x.WithTopic("X.*").WithTopic("*.B"));
这些主题重载也适用于SubscribeAsync
方法。
EasyNetQ
默认行为,当生成队列的名称时,使用消息类型名+subscription Id。例如:PartyInvitation
这个消息类型,命名空间为 EasyNetQ.Tests.Integration
,生成的队列名称为: EasyNetQ.Tests.Integration.PartyInvitation:EasyNetQ.Tests_schedulingTest1,这里假设subscription Id为 schedulingTest1.
控制队列名称
控制队列名称,用Queue attribute
在消息类上去注释。
[Queue("TestMessagesQueue", ExchangeName = "MyTestExchange")]
public class TestMessage
{
public string Text { get; set; }
}
// ...
bus.Subscribe<TestMessage>(string.Empty,
msg => Console.WriteLine(msg.Text));
这里我们告诉EasyNetQ要用TestMessagesQueue
作为队列名,用MyTestExchange
作为交换机名字。注意:传给Subscribe
方法的subscriptionsId
参数为空。假如你指定了subscriptionId
,那么subscriptionId
将会追加到队列名的后面。
让不是通过EasyNetQ发布的消息运作起来
使用QueueAttribute
允许消费来至于任何队列的消息。这可以用来消费来至于其他非EasyNetQ的框架发布的消息,只要满足一个条件:队列中消息有type属性设置。type
属性值被用在序列化消息时去决定消息的类型。只要这个属性设置为一些有意义的,这个消息就可以被消费。解码type
名是在ITypeNameSerializer.Deserialize
方法中做的。
如果你决定用自己的ITypeNameSerializer
实现,那么要小心你如何去执行反序列化方法,假如你的实现是CPU
计算密集型的,那么是危险的会限制你出队消息的速度。比如,程序集扫描没有类型缓存是一个坏主意。
命名队列注意事项
设置队列名称为空字符串将会使用默认命名规则。队列名最大255个字符(这是RabbitMQ client
类库强制规定)。队列名称可以是字母,数字,-
,下划线_
,点号.
,或冒号:
。队列名称以“amq.”开头,是预留的,为了预定义和标准化队列