我需要实现两个API来暂停和重新激活Rebus出列过程。
情况是服务总线Rebus和另一个软件共享相同的数据库和表来存储应用程序数据(不是队列),而后者的软件(我称之为“Xprocess”),在某个特定的时刻一天,锁定一些桌子约3分钟。由于Xprocess优先于Rebus消息执行,因此我们同意在此间隔期间通过Xprocess调用的Suspend和Resume api暂停Rebus。
我在徘徊,这是暂停Rebus消息执行的最佳方式。 考虑到无法添加暂停以下消息的特定消息,因为当Xprocess启动时,队列中可能已经有一些必须暂停的消息;
我的想法是在调用下一步之前在接收管道中添加一个询问“暂停”服务的步骤。 像这样:
public class HandlePausingServiceStep : IIncomingStep
{
readonly ILog _log;
readonly IPausingService _pausingService;
public HandlePausingServiceStep(IRebusLoggerFactory rebusLoggerFactory, IPausingService pausingService)
{
_log = rebusLoggerFactory.GetLogger<HandleApplicationExceptionsStep>();
_pausingService = pausingService;
}
public async Task Process(IncomingStepContext context, Func<Task> next)
{
while (_pausingService.Pause)
Thread.Sleep(5000);
await next();
}
}
答案 0 :(得分:1)
在做其他事情之前,我会考虑以下两个选项:
1)在数据库锁定期间,只需停止托管Rebus端点的进程。
如果您的端点作为Windows服务托管(在许多情况下可能应该这样做),您只需创建一个脚本net stop YourService
/ net start YourService
并使用Windows的任务计划程序来执行此操作。 / p>
2)使用Rebus的线程工作者API将工作者数量设置为0。
您可以这样做:
bus.Advanced.Workers.SerNumberOfWorkers(0);
然后是时候再做一次了:
bus.Advanced.Workers.SerNumberOfWorkers(5);
但显然你不应该从Rebus处理程序中执行此操作(因为它将如何获得再次唤醒它的消息?:D)
就个人而言,我更喜欢第一种选择,因为它非常简单,操作人员也很容易管理。
更新:在意识到此总线托管在Web应用程序的多个实例中之后,我想我会以稍微不同的方式解决这个挑战......
我认为一个可接受的解决方案是让Web应用程序后台的计时器定期检查数据库中特殊表中的配置标志值 - 这可以每5-10秒完成一次。
然后当发出标志信号时,所有实例都会SetNumberOfWorkers(0)
,从而有效地停止所有消息处理。
当再次举起旗帜时,计时器可以再次将工人加回来。
如果在数据库被锁定时没有发生消息处理是至关重要的,那么在提升/降低标志周围添加一点时间余量可能很重要。