AMQP
发布消息默认情况下是非事务性的,不能确保你的消息真正送达代理。AMQP
可以去指定事务性发布,但是RabbitMQ这样会非常慢,我们没有让EasyNetQ API
去支持此功能。为了高效的确保投递成功,RabbitMQ推荐使用'Publish Confirms'
。简单来讲,这是AMQP的一个扩展,当你的消息被代理成功接收以后,提供了一个回调支持。
成功接收意味着什么呢?
- 一个瞬态消息被确认那一刻,消息已进入队列。
- 一个持久化消息被确认时,消息会持久化到磁盘,或者每一个队列上的消息已被消费掉。
- 一个不可路由的瞬态消息被发后,就直接被确认了。
更多关于消息确认方面的内容,请看the announcement on the RabbitMQ blog.
启用消息确认,需要通过在连接字符串中设置 publisherConfirms=true
.
bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=true;timeout=10");
异步的bus.Publish(..)
方法在返回之前会等待消息确认。在超时之前(超时时间同样被配置在连接字符串中),消息确认会无失效,这将引起异常抛出。在异步发布方法上启用发布者确认将明显变慢。如果有性能上的担心,你应该考虑使用PublishAsync
方法。
bus.PublishAsync(new MyMessage
{
Text = "Hello World"
}).ContinueWith(task =>
{
// 这里仅仅检测task已完成
// IsCompleted 为true,如果task在故障状态中,
// 应该使用 if (task.IsCompleted && !task.IsFaulted) 去检测是否成功。
if (task.IsCompleted)
{
//Console.Out.WriteLine("{0} Completed", count);
}
if (task.IsFaulted)
{
Console.Out.WriteLine("\n\n");
Console.Out.WriteLine(task.Exception);
Console.Out.WriteLine("\n\n");
}
});
在收到确认消息之前,这将会返回。如果没有确认消息,或者收到一个NACK
确认信息,这个task
在失败状态下将会执行完成。
很多商业流程需要事件在未来的时间按照预定时间发布。例如,在初次与客户接触后,可以在未来某个时间去电话回访客户。EasyNetQ
可以用它的Future Publish
功能帮你实现这个功能。举例:这里我们使用FuturePublish
扩展方法去预定未来一个月后打销售回访电话。注意:FuturePublish
使用UTC
时间。
var followUpCallMessage = new FollowUpCallMessage(..);
bus.FuturePublish(DateTime.UtcNow.AddMonths(1),followUpCallMessage);
从现在开始一个月后,这个消息通过EasyNetQ
将会发布这个消息,任何FollowUpCallMessage
的订阅者将接收到一个原始消息拷贝。
FuturePublish
需要EasyNetQ.Scheduler
服务处于运行中状态。
它是如何运作的?
当你调用bus.FuturePublish(publishDate,Message)
时,EasyNetQ
包装这个消息到一个系统消息'ScheduleMe'
中,然后发布这个消息到RabbitMQ
。这个调度服务订阅这个消息。当它接收到一个ScheduleMe
消息时,它会存储这个消息到它的本地数据库中,这个调度服务去数据库查询日程日期到期的消息,当有任何消息到期时,它会从这个ScheduleMe
消息中解开原始的消息,然后发送消息到事件总线。
安装调度服务
- 在
SQL Server
中,创建一个名称为EasyNetQ.Scheduler
的数据库。 - 获取
EasyNetQ
源码
git clone git@github.com:mikehadlow/EasyNetQ.git - 在
Visual Studio
中打开EasyNetQ.2012
这个解决方案。在DatabaseScripts->EasyNetQ.Scheduler
文件夹下你会发现一些SQL
脚本。在EasyNetQ.Scheduler
数据库中打开并执行这些脚本。你需要先执行CreateWorkTables.sql
,其他是存储过程脚本,执行这些脚本没有先后顺序。 - 编译这个解决方案。
- 找到
\Source\EasyNetQ.Scheduler\bin\Debug
这个文件夹,拷贝其下所有文件到你选择的部署文件夹中。 - 用一个文本编辑器打开
EasyNetQ.Scheduler.exe.Config
,修改'rabbit'
和'scheduleDb'
连接字符串为你的RabbitMQ
代理和SQL Server
各自的实例。 - 打开控制台窗口,进入你部署
EasyNetQ.Scheduler
所在的文件夹。 - 运行后面的命令,把
EasyNetQ.Scheduler
安装为一个windows 服务。
EasyNetQ.Scheduler.exe install
执行后,显示下面信息:
Configuration Result: [Success] Name EasyNetQ.Scheduler [Success] ServiceName EasyNetQ.Scheduler Topshelf v3.1.106.0, .NET Framework v4.0.30319.18051
Running a transacted installation.
Beginning the Install phase of the installation. Installing EasyNetQ.Scheduler service Installing service EasyNetQ.Scheduler... Service EasyNetQ.Scheduler has been successfully installed. Creating EventLog source EasyNetQ.Scheduler in log Application...
The Install phase completed successfully, and the Commit phase is beginning.
The Commit phase completed successfully.
The transacted install has completed.
现在你应该能够调用FuturePublish
方法,在指定时间到来时,你会收到消息。
卸载EasyNetQ.Scheduler
,运行:
EasyNetQ.Scheduler.exe uninstall