使用NServiceBus发布到本地订阅者

时间:2012-03-20 16:54:30

标签: nservicebus

我在this问题中解释了NServiceBus的用例。本质上,有一个ImportProductCommand消息的消息处理程序。通常,在另一个处理程序收到ImportProductsCommand后,会将这些消息的集合发送到处理程序,ImportProductsCommand指定要导入的产品集。需要知道set导入的状态,因此使用saga来管理导入状态。 ImportProductCommand的处理程序在完成时发布ProductImportedEvent消息和ProductImportFailedEvent消息。该传奇使用在首次接收时分配给该消息的ID来订阅那些将它们与发起的ImportProductsCommand消息相关联的消息。

public class ProductImportSaga : NServiceBus.Saga.Saga<ProductImportSagaData>,
    IAmStartedByMessages<ImportProductsCommand>,
    IHandleMessages<IProductImportedEvent>,
    IHandleMessages<IProductImportFailedEvent>
{
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<IProductImportedEvent>(x => x.ImportId, x => x.CorrelationId);
        ConfigureMapping<IProductImportFailedEvent>(x => x.ImportId, x => x.CorrelationId);
    }

    public void Handle(ImportProductsCommand message)
    {
        this.Data.ImportId = message.Id;
        this.Data.Total = message.SKUs.Length;
        foreach (var command in message.SKUs.Select(sku => new ImportProductCommand(message.SupplierId, sku, message.ImportImage, message.Id)))
            this.Bus.SendLocal(command);    // send to local handler shown below
    }

    public void Handle(IProductImportedEvent message)
    {
        this.Data.OnCompleted();
    }

    public void Handle(IProductImportFailedEvent message)
    {
        this.Data.OnFailed();
    }
}

单个ImportProductCommand消息的处理程序如下所示:

// handles messages sent by saga above (or sent individually by WCF service)
public class ImportProductHandler : IHandleMessages<ImportProductCommand>
{
    public IBus Bus { get; set; } 

    public void Handle(ImportProductCommand message)
    {
        // importing logic here and upon success:
        if (success)
        {
           this.Bus.Publish(new ProductImportedEvent(correlationId: message.Id));
        }
        else
        {
           this.Bus.Publish(new ProductImportFailedEvent(correlationId: message.Id));
        }
    }
}

这个问题是,当事件消息发布时,它们会被放置在与托管单个处理程序和saga的进程关联的队列中。当发生这种情况时,队列中可能会有很多消息最初由传奇发送以响应ImportProductsMessage。这意味着在处理排队的ImportProductCommand消息之后,saga将不会接收这些事件,因此不会及时更新批量导入的处理状态。如果我在不同的进程中托管saga,那么它将接收消息而无需等待命令队列进行处理。有没有办法在同一进程中托管处理程序和传奇时实现相同的效果?基本上,我希望以不同于ImportProductCommand消息的顺序处理事件消息,即使它们位于同一队列中,以便saga可以处理这些事件并相应地更新其状态。这有可能还是有更好的方法来实现这个结果?我试图使用First<T>指定消息处理程序排序无效,为密切相关的逻辑部署两个不同的主机似乎有点过分。

1 个答案:

答案 0 :(得分:2)

NSB没有优先级概念,因此通常使用另一个端点来执行工作。这听起来就像是你的工作分配,你可能想看看Distributor。在该模型中,Saga将维持整个工作单元的状态,而每个端点将处理实际处理。如果事情开始变慢,这将允许您动态添加其他端点。

如果您不想实现完整的分发服务器,那么至少将实际工作推送到另一个端点可以减轻对优先级的任何需求。