EasyNetQ v0.7.1.30版本有了一个简单AutoSubscriber。你能够使用它很容易的去扫描指定程序集中实现了IConsume 或 IConsumeAsync接口的类,然后这个自动订阅者让这些消费者订阅到你的事件总线中。IConsume的实现将使用事件总线的Subscribe方法,同时IConsumeAsync的实现使用事件总线的SubscribeAsync方法,详情参看EasyNetQ之订阅。你当然能够让你的消费者处理多个消息。让我们看一些示例。

注意:从0.13.0版本开始,所有的AutoSubscriber类都在EasyNetQ.AutoSubscribe命名空间中。因此请添加下面的using语句。

using EasyNetQ.AutoSubscribe;

让我们定义一个简单消费者,处理三个消息:MessageA,MessageB和MessageC。

public class MyConsumer : IConsume<MessageA>,
IConsume<MessageB>,
IConsumeAsync<MessageC>
{
public void Consume(MessageA message) {...} public void Consume(MessageB message) {...} public Task Consume(MessageC message) {...}
}

首先创建一个新的AutoSubscriber实例,传你的IBus实例和subscriberId前缀给AutoSubscriber的构造函数。这个subscriberId前缀会作为所有自动生成的subscriberIds的前缀。但是不能自定义subscriberId(参看下文)。

注册在相同程序集中的所有其他消费者,我们仅仅需要去传包含你的消费者所在的程序集给这个方法:AutoSubscriber.Subscribe(assembly)。注意!,这些事情你应该只做一次,最好在应用启动的时候。

var subscriber = new AutoSubscriber(bus,
"my_applications_subscriptionId_prefix");
subscriber.Subscribe(Assembly.GetExecutingAssembly());

通过主题订阅

默认的AutoSubscriber将不带主题的绑定。下面的例子中MessageA被注册到两个主题。

注意! 如果你运行下面代码,没有加上ForTopic属性标签,它将有一个"#"路由Key,这个Key将会选择任何订阅这个消息类型的订阅者。假定在默认端口上且admin插件已被安装,简单访问http://localhost:15672/#/queues,如果需要请解除绑定的路由。

public class MyConsumer : IConsume<MessageA>,
IConsume<MessageB>,
IConsumeAsync<MessageC>
{
[ForTopic("Topic.Foo")]
[ForTopic("Topic.Bar")]
public void Consume(MessageA message) {...} public void Consume(MessageB message) {...} public Task Consume(MessageC message) {...}
} //通过主题发布
var bus = RabbitHutch.CreateBus("host=localhost"); //被选中
var msg1 = new MessageA("topic.foo");
bus.Publish(msg1, "Topic.Foo"); //被选中
var msg2 = new MessageA("topic.bar");
bus.Publish(msg1, "Topic.Bar"); //不会被选中
var msg3 = new MessageA("no pick up);
bus.Publish(msg3);

指定一个特定的SubscriptionId

AutoSubscriber 默认情况下为每一组Message/Consumer生成一个唯一的SubscriptionId。这意味着当相同的消费者启动多个实例后,这些实例将会从相同队列中循环消费消息。

如果你希望subscriptionId是固定的,你能通过带有AutoSubscriberConsumerAttribute属性标签的Consume方法实现。为什么你会让SubscriptionId是固定的,可以阅读这里

假如,消费MessageB消息的Consume方法需要固定的SubscriptionId。仅仅需要使用AutoSubscriberConsumerAttribute属性标签,为其SubscriptionId设置一个值。

[AutoSubscriberConsumer(SubscriptionId = "MyExplicitId")]
public void Consume(MessageB message) { }

控制SubscriptionId的生成

你当然也可以控制实际的SubscriptionId的生成,只要用AutoSubscriber.GenerateSubscriptionId : Func<ConsumerInfo, string>替换就可以实现。

var subscriber = new AutoSubscriber(bus)
{
CreateConsumer = t => objectResolver.Resolve(t),
GenerateSubscriptionId = c => AppDomain.CurrentDomain.FriendlyName
+ c.ConcreteType.Name
};
subscriber.Subscribe(Assembly.GetExecutingAssembly());

注意! 这只是实现的一个样例。请确保你已经读过并理解了SubscriptionId值的重要价值。

控制消费者配置设置

当使用autosubsriber去订阅队列消息,你能够设置ISubscriptionConfiguration值,例如AutoDelete,Priority 等。

var subscriber = new AutoSubscriber(bus)
{
ConfigureSubscriptionConfiguration = c => c.WithAutoDelete()
.WithPriority(10)
};
subscriber.Subscribe(Assembly.GetExecutingAssembly());

或者,你可以用在consume方法上用属性标签的方式。

public class MyConsumer : IConsume<MessageA>
{
[SubscriptionConfiguration(CancelOnHaFailover = true, PrefetchCount = 10)]
public void Consume(MessageA message) {...}
}

让AutoSubscriber使用容器

AutoSubscriber 有一个属性:MessageDispatcher,这个属性允许插入你自己消息调度代码。这样允许你从IoC容器中或者其他第三方任务调度中,解析你自己的消费者。

让我们写一个自定义的IAutoSubscriberMessageDispatcher实现,从 Windsor IoC 容器中去解析消费者。

public class WindsorMessageDispatcher : IAutoSubscriberMessageDispatcher
{
private readonly IWindsorContainer container; public WindsorMessageDispatcher(IWindsorContainer container)
{
this.container = container;
} public void Dispatch<TMessage, TConsumer>(TMessage message) where TMessage : class where TConsumer : IConsume<TMessage>
{
var consumer = container.Resolve<TConsumer>();
try
{
consumer.Consume(message);
}
finally
{
container.Release(consumer);
}
} public Task DispatchAsync<TMessage, TConsumer>(TMessage message) where TMessage: class where TConsumer: IConsumeAsync<TMessage>
{
var consumer = _container.Resolve<TConsumer>();
return consumer.Consume(message).ContinueWith(t=>_container.Release(consumer));
}
}

现在,我们需要注册消费者到我们的IoC容器中。

var container = new WindsorContainer();
container.Register(
Component.For<MyConsumer>().ImplementedBy<MyConsumer>()
);

下一步,让AutoSubscriber 用我们自定义的IMessageDispatcher:

var bus = RabbitHutch.CreateBus("host=localhost");

var autoSubscriber = new AutoSubscriber(bus, "My_subscription_id_prefix")
{
MessageDispatcher = new WindsorMessageDispatcher(container)
};
autoSubscriber.Subscribe(GetType().Assembly);
autoSubscriber.SubscribeAsync(GetType().Assembly);

现在每一次消息到来是,一个新的消费者实例,将会从我们自定义的容器中拿到。

英文地址:https://github.com/EasyNetQ/EasyNetQ/wiki/Auto-Subscriber

本文地址:http://www.cnblogs.com/HuangLiang/p/EasyNetQ_AutoSubscriber.html

我的微信订阅号:open_dotNET

16-EasyNetQ之自动订阅者的更多相关文章

  1. 【EasyNetQ】- 自动订阅者

    从v0.7.1.30开始,EasyNetQ简单易用AutoSubscriber.你可以用它来轻松地扫描实现任何接口的类的特定组件IConsume<T>或IConsumeAsync<T ...

  2. EasyNetQ使用(八)【对延迟消息插件的支持,自动订阅者】

    RabbitMQ延迟消息插件仍然在实验阶段.你使用这个功能要自担风险. RabbitMQ延迟消息插件为RabbitMQ增加了新的交换机类型,允许延时消息投递. EasyNetQ为交换机通过定义一种新的 ...

  3. iOS 自动订阅开发

    一.代码逻辑 关于iOS 订阅.自动订阅 本身功能开发很简单.跟正常的购买没什么大的差异.唯一需要特殊处理(自动订阅)的是, 在APP启动时候要增加侦听: [[SKPaymentQueue defau ...

  4. 【EasyNetQ】- 发布/订阅模式

    EasyNetQ支持的最简单的消息传递模式是发布/ 订阅.这种模式是消除消费者信息提供者的绝佳方式.出版商简单地向全世界说,“这已经发生了”或“我现在有了这些信息”.它不关心是否有人正在倾听,他们可能 ...

  5. 加密算法使用(二):使用MD5加密字符串(另:byte数组转16进制自动补零方法写法)

    public static void main(String args[]) throws NoSuchAlgorithmException { String s = new String(" ...

  6. 该死的Ubuntu 16.04不自动续租DHCP的IP

    BUG,这是一个BUG,参考:https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1551351,如果不自动续租IP,导致的问题就是网线灯还 ...

  7. EMQ ---客户端上线自动订阅主题

    通过修改配置文件即可实现. emq v2.3.11,软件架构做了调整,把功能集成在了emq_modules模块,/data/loaded_plugins默认会加载emq_modules. 我们只需要改 ...

  8. Ubuntu 16.04开机自动挂载硬盘分区(转)

    说明:如果挂载以前旧硬盘分区时不需要第2.3步! 1.查看Linux硬盘信息: sudo fdisk -l 2.格式化新硬盘(很危险,注意操作时确定硬盘分区的位置): sudo mkfs.ext4 / ...

  9. Ubuntu 16.04开机自动开启数字键盘NumLock

    注意:以下方法不适合在登录时开启,只能是登录后开启.而且我经过测试之后会自动暗下去,但是不影响功能使用.这个是BUG的修复方法:https://askubuntu.com/questions/5090 ...

随机推荐

  1. springmvc的RESTful风格

    springmvc对RESTful得支持RESTful架构,就是目前最流行得一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以挣得到越来越多网站的采用. RESTful(即Repres ...

  2. 201621123003《Java程序设计》第一周学习总结

    #1. 本周学习总结 本周主要学习了Java的jdk.jvm.jre等基本概念,Java的发展史,知道Java语言的跨平台.面向对象等主要特点,简单了解了Java程序的编译和运行过程.对于学习Java ...

  3. PostgreSQL流复制记录

    参考了别人的部分,添加了自己在实践中的内容,仅做记录. 1.同步流复制中 主机操作 1.1postgresql.conf wal_level = hot_standby # 这个是设置主为wal的主机 ...

  4. java事务(三)——自己实现分布式事务

    在上一篇<java事务(二)——本地事务>中已经提到了事务的类型,并对本地事务做了说明.而分布式事务是跨越多个数据源来对数据来进行访问和更新,在JAVA中是使用JTA(Java Trans ...

  5. 用java网络编程中的TCP方式上传文本文件及出现的小问题

    自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...

  6. 深入理解java虚拟机-第三章

    1.概述 2.对象已死吗? 引用计数器 给对象添加一个引用计数器,每当有引用时,计数器加1,引用失效时,计数器减1:任何时刻计数器为0的对象就是不可能再被使用的. 若对象是循环引用,则无法处理.JVM ...

  7. Spring3.x JSR-303

    JSR303介绍 JSR303-Bean Validation描述:This JSR will define a meta-data model and API for JavaBeanTM vali ...

  8. 剑指offer-第四章解决面试题思路(字符串的排序)

    题目:输入一个字符串,打印出该字符串的全排列. 思路:将整个字符串分成两部分,第一部分为一个字符,将该字符和该字符后面的字符(直到最后一个字符)依次交换,确定第一个字符:然后固定第一个字符,将后面的字 ...

  9. RecyclerView 初体验

    网上看了很多 RecyclerView 的教程,也结合学长的代码,终于实现了一个不错看的过去的List 可以通过左滑删除Item 长按Item或者点击按钮,可以对Item进行拖拽 更具体的内容会写在代 ...

  10. 配置linux下面python的开发环境

    1.首先安装Python开发环境 http://blog.csdn.net/testcs_dn/article/details/51253365 2.安装django开发环境 http://blog. ...