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