如何在另一个进程锁定表时挂起Rebus执行



我需要实现两个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();
    }
}

在做任何其他事情之前,我会考虑以下两个选项:

1)在数据库被锁定期间,只需停止驻留Rebus端点的进程。

如果你的端点是作为Windows服务托管的(在许多情况下它可能应该),你可以简单地制作一个脚本net stop YourService/net start YourService,并使用Windows的任务调度程序来完成它。

2)使用Rebus的线程工作器API将工作器的数量设置为0。

你可以这样做:

bus.Advanced.Workers.SerNumberOfWorkers(0);

然后当该做某事的时候:

bus.Advanced.Workers.SerNumberOfWorkers(5);

,但显然不应该在Rebus处理程序中这样做(因为它将如何获得再次唤醒它的消息?: D)

就我个人而言,我更喜欢第一种选择,因为它很简单,对操作人员来说很容易管理。


更新:在意识到这个总线托管在一个web应用程序的多个实例后,我想我会以一种稍微不同的方式解决这个挑战…

我认为一个可以接受的解决方案是在web应用程序的后台定时检查数据库中一个特殊表中的配置标志值——这可以每5-10秒或其他时间完成一次。

然后当标志被标记时,所有实例将SetNumberOfWorkers(0),从而有效地停止所有消息处理。

当标志再次升起时,计时器可以再次添加工人。

如果在数据库被锁定时不发生任何消息处理是至关重要的,那么在升/降标志周围添加一点时间间隔可能很重要。

相关内容

  • 没有找到相关文章

最新更新