使用NServiceBus发布到本地订阅服务器

使用NServiceBus发布到本地订阅服务器,nservicebus,Nservicebus,我有一个关于NServiceBus的用例。本质上,ImportProductCommand消息有一个消息处理程序。通常,在另一个处理程序接收到指定要导入的产品集的ImportProductsCommand后,这些消息的集合会发送到处理程序。需要知道集合导入的状态,因此使用saga来管理导入状态。ImportProductCommand的处理程序在完成时发布ProductImportedEvent消息和ProductImportFailedEvent消息。saga使用第一次收到消息时分配给消息的I

我有一个关于NServiceBus的用例。本质上,ImportProductCommand消息有一个消息处理程序。通常,在另一个处理程序接收到指定要导入的产品集的ImportProductsCommand后,这些消息的集合会发送到处理程序。需要知道集合导入的状态,因此使用saga来管理导入状态。ImportProductCommand的处理程序在完成时发布ProductImportedEvent消息和ProductImportFailedEvent消息。saga使用第一次收到消息时分配给消息的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();
    }
}
公共类ProductImportSaga:NServiceBus.Saga.Saga,
我开始发短信,
我的手机短信,
IHandleMessages
{
公共覆盖无效配置HowtoFindsaga()
{
配置映射(x=>x.ImportId,x=>x.CorrelationId);
配置映射(x=>x.ImportId,x=>x.CorrelationId);
}
公共无效句柄(ImportProductsCommand消息)
{
this.Data.ImportId=message.Id;
this.Data.Total=message.SKUs.Length;
foreach(message.SKUs.Select中的var命令(sku=>newimportproductcommand(message.SupplierId,sku,message.ImportImage,message.Id)))
this.Bus.SendLocal(命令);//发送到如下所示的本地处理程序
}
公共无效句柄(IPProductImportedEvent消息)
{
this.Data.OnCompleted();
}
公共无效句柄(IPProductImportFailedEvent消息)
{
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发送的消息(或WCF服务单独发送的消息)
公共类ImportProductHandler:IHandleMessages
{
公共IBus总线{get;set;}
公共无效句柄(ImportProductCommand消息)
{
//在此处和成功后导入逻辑:
如果(成功)
{
this.Bus.Publish(新产品导入事件(correlationId:message.Id));
}
其他的
{
this.Bus.Publish(新产品导入失败事件(correlationId:message.Id));
}
}
}

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

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


如果您不想实施完整的分发服务器,然后,至少将实际工作推送到另一个端点将减轻对优先级的任何需要。

我认为使用单独的端点可能是一个可行的方法,因为还有另一个要求支持手动请求的各个导入,这些导入的优先级高于批处理导入命令排队的各个导入。您可以然后指定其中一个节点仅处理手动导入,并通过一些UI与之交互。