[英]Using a NServicebus saga to serialize execution of long-running endpoint handlers
我們正在嘗試使用 Saga 序列化業務對象列表的處理。
現在,沒有 Saga,我們只需循環遍歷對象列表,然后觸發bus.Send(new ProcessBusinessObejct(obj))
異步以讓處理程序執行。 所以處理或多或少是並行發生的,取決於這個設置,我相信:
endpointConfiguration.LimitMessageProcessingConcurrencyTo( 4 );
這工作正常,但並發處理程序的數量現在在數據庫上很難。
串聯觸發這些處理程序是可以的,即僅當當前進程完成(失敗或成功)時才繼續下一個。 我們不想將並發設置為 1,它會影響端點中的所有處理程序。
這個想法是使用 Scatter/Gather 模式和 Saga 來跟蹤對象的數量並使用 a 計數(總計數、失敗計數、成功計數)更新狀態機,最后在列表為完成/空。
問題是
A)我不確定如何跟蹤傳奇中的列表。 SagaData 需要一個 List 來保存所有對象嗎? 然后在處理程序發出它已完成處理的信號時刪除一個實例。 傳奇不支持分層數據,因此沒有列表或列表。 我相信在 NSB v7 中仍然如此。
和 B) 使用 saga 是否可行或矯枉過正,還是有更簡單的方法來實現這一目標?
我們正在使用 Sql Server 持久性和傳輸以及 NSB 7。
非常感謝任何輸入!
我認為你正在尋找這樣做。 請注意,根據您使用的持久層,您可能需要將實際導入與更新 saga 狀態分開。 我在這里寫了關於這個的博客。
Saga 數據也可以存儲一個列表,但我認為在大多數情況下你可以擺脫計數。 另一個重要的注意事項(盡管應該很明顯)是,如果消息無法處理並進入錯誤隊列(例如,ImportData 中未捕獲的異常),則整個 saga 將保持不完整,直到該消息被重試和處理。
public class MySaga : Saga<MySagaData>
: IAmStartedByMessages<StartTheProcess>,
IHandleMessages<ImportData>,
IHandleMessages<ImportFinished>
{
public async Task Handle(StartTheProcess message, IMessageHandlerContext context)
{
Data.ObjectsToImport = message.ObjectCount;
Data.JobID = Guid.NewGuid(); //To generate a correlation ID to connect future messages back to this saga instance
foreach(var id in message.ObjectIdsToImport)
{
await context.SendLocal(new ImportData
{
JobID = Data.JobID //You need this to correlate messages back to the saga
//Anything else you need to pass on to ImportData
ObjectIdToImport = id
}
});
}
public async Task Handle(ImportData message, IMessageHandlerContext context)
{
//import the data and increment the counter
var result = ImportData(message.ObjectIdToImport);
if(result == Result.Success)
{
Data.SuccessImport++;
}
else
{
Data.FailedImport++;
}
await CheckIfFinished(context);
}
public async Task Handle(ImportFinished message, IMessageHandlerContext context)
{
//do any post cleanups or Mark as complete
MarkAsComplete();
return Task.CompletedTask;
}
private async Task CheckIfFinished(IMessageHandlerContext context)
{
if(Data.SuccessImport + Data.FailedImport == Data.ObjectsToImport)
{
//Everything is done
context.SendLocal(new ImportFinished { JobID = Data.JobID });
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.