NServiceBus-使用相同的密钥排队
情景: 我用10个步骤构建了一个传奇。它正在更新各种系统,整个故事可能需要几分钟才能完成 这个传奇故事是从另一个系统的数据开始的,在这个系统中,用户输入关于客户的信息 我无法看到用户何时在他们的系统中输入完数据,但我正在每隔x分钟从系统中读取带有更改的数据 我的问题是,每当我开始一个关于某个客户的传奇故事时,我需要确保之前关于同一个客户的传奇故事已经结束。 如果用户花费10分钟输入数据,系统可能会在同一客户上启动5个流,并且流可能会超过以前的流,并将数据弄乱 有人知道我如何解决这个问题吗 提前谢谢NServiceBus-使用相同的密钥排队,nservicebus,nservicebus-sagas,Nservicebus,Nservicebus Sagas,情景: 我用10个步骤构建了一个传奇。它正在更新各种系统,整个故事可能需要几分钟才能完成 这个传奇故事是从另一个系统的数据开始的,在这个系统中,用户输入关于客户的信息 我无法看到用户何时在他们的系统中输入完数据,但我正在每隔x分钟从系统中读取带有更改的数据 我的问题是,每当我开始一个关于某个客户的传奇故事时,我需要确保之前关于同一个客户的传奇故事已经结束。 如果用户花费10分钟输入数据,系统可能会在同一客户上启动5个流,并且流可能会超过以前的流,并将数据弄乱 有人知道我如何解决这个问题吗 提前谢
Ole如果不更改saga以及客户端系统发送的消息,则无法解决此问题 您的问题是,saga可能被配置为在收到某个消息类型时启动,该消息类型由客户机应用程序在用户每次更改客户时生成 我们将此消息称为:
public class ClientTypedSomethingAboutCustomer
{
int CustomerId {get;set;}
...
}
您的传奇故事将设置如下:
public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
{
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<ClientTypedSomethingAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
...
}
...
}
public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
,IHandleMessages<ClientTypedSomethingElseAboutCustomer>
{
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<ClientTypedSomethingAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
ConfigureMapping<ClientTypedSomethingElseAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
}
...
}
那么你的传奇故事会是这样的:
public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
{
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<ClientTypedSomethingAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
...
}
...
}
public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
,IHandleMessages<ClientTypedSomethingElseAboutCustomer>
{
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<ClientTypedSomethingAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
ConfigureMapping<ClientTypedSomethingElseAboutCustomer>
(message => message.CustomerId).ToSaga(saga => saga.CustomerId);
}
...
}
public-class-CustomerSaga:Saga,IAmStartedByMessages
,IHandleMessages
{
公共覆盖无效配置HowtoFindsaga()
{
配置映射
(message=>message.CustomerId).ToSaga(saga=>saga.CustomerId);
配置映射
(message=>message.CustomerId).ToSaga(saga=>saga.CustomerId);
}
...
}
这将确保有关客户的所有消息都将路由到单个saga实例
通过在单线程模式下运行NServiceBus,可以实现近似的排队行为。这可能会限制为客户创建并发传奇,但我不想依赖于此 janpieter_z和@tom redfern都是正确的:确保你能将这个传奇故事映射到某种类型的客户id 您还可以实现查找与传入消息相对应的正确传奇 此外,如果多条消息未按正确顺序到达,则可以将其设置为“IAmStartedByMessages”
最后,谁在向你的传奇故事发送信息?难道这部传奇不应该负责发送收集数据的请求吗?可能每隔10秒通过超时或其他方式,直到几分钟内没有收到任何信息,或者处理程序以不同的消息进行答复?您能将您的唯一属性设置为客户id吗?如果是这样的话,你可以让故事开始的信息也被映射到故事并由故事处理。这样,如果启动了客户id为1的saga,并且收到了一条新消息(为客户1接收了更新),则会导致由相同的saga处理。如果这不起作用,请提供有关saga映射的简短代码片段+初始化消息您还可以实现文档中描述的复杂saga查找逻辑:“本质上,IAmStartedByMessages的语义是:如果找不到现有实例,则创建新实例。”