在使用耐用的編排系統時,升級與降級編排是關鍵考量。 若編排中斷後(例如主機更新期間)恢復,Durable Task Scheduler 會重播編排事件,確保所有先前步驟都成功執行後再進行下一步。 此舉確保可靠性,是持久執行範式的核心承諾之一。
如果編排在兩次部署間改變,所採取的步驟可能不再相同。 此時系統會拋出一個 NonDeterministicError,而非讓編排繼續。
編排版本控制 防止與非確定性相關的問題,讓你能無縫處理新舊編排。 Durable Task Scheduler 有兩種不同的版本管理方式,你可以單獨使用或合併使用:
這很重要
目前,長期工作 SDK 不適用於 JavaScript 和 PowerShell。
這很重要
目前,長期工作 SDK 不適用於 JavaScript 和 PowerShell。
用戶端/內容型條件式版本控制
要讓編排有一個版本,必須先在客戶端進行設定。
.NET SDK 使用標準的主機建構擴充套件。
備註
自 v1.9.0 起,已在 .NET SDKMicrosoft.DurableTask.Client.AzureManaged 中提供。
builder.Services.AddDurableTaskClient(builder =>
{
builder.UseDurableTaskScheduler(connectionString);
builder.UseDefaultVersion("1.0.0");
});
備註
自 Java SDKcom.microsoft:durabletask-client 1.6.0 起提供。
public DurableTaskClient durableTaskClient(DurableTaskProperties properties) {
// Create client using Azure-managed extensions
return DurableTaskSchedulerClientExtensions.createClientBuilder(properties.getConnectionString())
.defaultVersion("1.0")
.build();
}
c = DurableTaskSchedulerClient(host_address=endpoint, secure_channel=secure_channel,
taskhub=taskhub_name, token_credential=credential,
default_version="1.0.0")
將版本新增至用戶端後,任何由此主機啟動的協調流程都會使用版本1.0.0。 該版本是一個簡單的字串,接受任意值。 然而,SDK 嘗試將其轉換為 。NET 的 System.Version.
- 如果 能 轉換,該函式庫會用於比較。
- 若 不合 ,則使用簡單的字串比較。
在客戶端提供版本後,也能在TaskOrchestrationContext中使用該版本,也就是說你可以在條件語句中使用該版本。 只要新版編排版本有適當的封控,舊版和新版編排版就能在同一主機上同時執行。
Example:
[DurableTask]
class HelloCities : TaskOrchestrator<string, List<string>>
{
private readonly string[] Cities = ["Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo"];
public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, string input)
{
List<string> results = [];
foreach (var city in Cities)
{
results.Add(await context.CallSayHelloAsync($"{city} v{context.Version}"));
if (context.CompareVersionTo("2.0.0") >= 0)
{
results.Add(await context.CallSayGoodbyeAsync($"{city} v{context.Version}"));
}
}
Console.WriteLine("HelloCities orchestration completed.");
return results;
}
}
一旦你將版本新增到客戶端,任何由此客戶端啟動的協作流程將會使用版本 1.0.0。 該版本是一個簡單的字串,接受任意值。
在客戶端提供版本後,也會讓它在 TaskOrchestration中提供,這表示你可以在條件語句中使用該版本。 只要新版的編排版本具備適當的版本門控,舊版與新版編排版就能在同一客戶端上同時執行。
Example:
public TaskOrchestration create() {
return ctx -> {
List<String> results = new ArrayList<>();
for (String city : new String[]{ "Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo" }) {
results.add(ctx.callActivity("SayHello", city, String.class).await());
if (VersionUtils.compareVersions(ctx.getVersion(), "2.0.0") >= 0) {
// Simulate a delay for newer versions
results.add(ctx.callActivity("SayGoodbye", city, String.class).await());
}
}
ctx.complete(results);
};
}
一旦你將版本加入到客戶端,任何由此客戶端啟動的編排都會使用 1.0.0 版本。 該版本是一個簡單的字串,使用解析 packaging.version,支援語意版本比較,並接受任何值。
在客戶端提供版本後,也會在task.OrchestrationContext中提供,這意味著你可以在條件語句中使用該版本。 只要新版的編排版本具備適當的版本門控,舊版與新版編排版就能在同一客戶端上同時執行。
Example:
def orchestrator(ctx: task.OrchestrationContext, _):
if ctx.version == "1.0.0":
# For version 1.0.0, we use the original logic
result: int = yield ctx.call_activity(activity_v1, input="input for v1")
elif ctx.version == "2.0.0":
# For version 2.0.0, we use the updated logic
result: int = yield ctx.call_activity(activity_v2, input="input for v2")
else:
raise ValueError(f"Unsupported version: {ctx.version}")
return {
'result': result,
}
在這個例子中,我們將 SayGoodbye 活動添加到 HelloCities 編排中。 此活動僅適用於編排版本 2.0.0及更新版本。 使用簡單條件陳述,任何版本小於 的 2.0.0 編排都能繼續運作,且任何新的編排都包含該新活動。
使用用戶端版本設定的時機
雖然用戶端版本管理提供了最簡單的版本編排機制,但與版本互動可能非常耗費程式設計。 如果有以下情況,請使用客戶端版本管理:
- 你想要所有版本都有標準版本,或者
- 你需要針對特定版本自訂邏輯。
工作者為基礎的版本控制
雖然協調流程仍需用戶端版本來設定版本,但工作人員型版本管理方法能協助您在編排中避免用到條件判斷。 工作人員會在開始執行前,選擇如何對不同版本的協調流程採取行動。
工作程序版本控制需要設定下列欄位:
工作人員的版本。
預設版本適用於由工作人員啟動的子協調流程。
工作人員用來與協調流程版本配對的原則。
名稱 說明 沒有 在處理工作時,版本不會被考慮 Strict 協調流程和背景工作角色中的版本必須完全相符 CurrentOrOlder 協調流程中的版本必須等於或小於背景工作角色中的版本 如果版本不符合比對原則,工作人員將採取的原則。
名稱 說明 拒絕 協調流程被工作人員拒絕,但仍留在工作佇列中以在稍後再進行嘗試。 失敗 協調流程失敗,且已從工作佇列中移除
類似於用戶端版本管理,你可以透過標準主機建構器模式設定這些欄位。
備註
自 v1.9.0 起可在 .NET SDK (Microsoft.DurableTask.Worker.AzureManaged) 中使用。
builder.Services.AddDurableTaskWorker(builder =>
{
builder.AddTasks(r => r.AddAllGeneratedTasks());
builder.UseDurableTaskScheduler(connectionString);
builder.UseVersioning(new DurableTaskWorkerOptions.VersioningOptions
{
Version = "1.0.0",
DefaultVersion = "1.0.0",
MatchStrategy = DurableTaskWorkerOptions.VersionMatchStrategy.Strict,
FailureStrategy = DurableTaskWorkerOptions.VersionFailureStrategy.Reject,
});
});
備註
自 v1.6.0 起可在 Java SDK (com.microsoft:durabletask-client) 中使用。
private static DurableTaskGrpcWorker createTaskHubServer() {
DurableTaskGrpcWorkerBuilder builder = new DurableTaskGrpcWorkerBuilder();
builder.useVersioning(new DurableTaskGrpcWorkerVersioningOptions(
"1.0",
"1.0",
DurableTaskGrpcWorkerVersioningOptions.VersionMatchStrategy.CURRENTOROLDER,
DurableTaskGrpcWorkerVersioningOptions.VersionFailureStrategy.REJECT));
// Orchestrations can be defined inline as anonymous classes or as concrete classes
builder.addOrchestration(new TaskOrchestrationFactory() {
@Override
public String getName() { return "HelloCities"; }
@Override
public TaskOrchestration create() {
return ctx -> {
List<String> results = new ArrayList<>();
for (String city : new String[]{ "Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo" }) {
results.add(ctx.callActivity("SayHello", city, String.class).await());
}
ctx.complete(results);
};
}
});
// Activities can be defined inline as anonymous classes or as concrete classes
builder.addActivity(new TaskActivityFactory() {
@Override
public String getName() { return "SayHello"; }
@Override
public TaskActivity create() {
return ctx -> {
String input = ctx.getInput(String.class);
return "Hello, " + input + "!";
};
}
});
return builder.build();
}
with DurableTaskSchedulerWorker(host_address=endpoint, secure_channel=secure_channel,
taskhub=taskhub_name, token_credential=credential) as w:
# This worker is versioned for v2, as the orchestrator code has already been updated
# CURRENT_OR_OLDER allows this worker to process orchestrations versioned below 2.0.0 - e.g. 1.0.0
w.use_versioning(worker.VersioningOptions(
version="2.0.0",
default_version="2.0.0",
match_strategy=worker.VersionMatchStrategy.CURRENT_OR_OLDER,
failure_strategy=worker.VersionFailureStrategy.FAIL
))
w.add_orchestrator(orchestrator)
w.add_activity(activity_v1)
w.add_activity(activity_v2)
w.start()
失效策略
拒絕
當期望的行為是讓協調流程在之後或在不同的工作人員上重試時,請使用Reject失敗原則。 在 Reject 發生失敗時:
- 一個協調流程被拒絕並返回到工作佇列。
- 協調流程被移出工作佇列。
- 移出工作佇列的協調流程可能會分配到不同的工作人員,或是再次由同一個工作人員處理。
這個過程會重複,直到有能處理編排的工作人員可用。 此策略能無縫處理更新編排的部署。 隨著部署進行,無法處理協調流程的工作人員會加以拒絕,而能處理的工作人員就會進行處理。
能夠混合工作人員與協調流程版本,允許像藍綠部署之類的情境。
Fail
當沒有其他預期版本時,請使用Fail失敗原則。 在此情況下,新版本是異常現象,任何工作人員都不應該嘗試處理它。 持久任務排程器未能完成調排,導致進入終端狀態。
使用工作程序版本控制的時機
在完全不應執行未知或不支援的協調流程的情境中,請使用工作人員版本管理。 背景工作角色版本設定會停止協調流程執行,而不是將版本處理程式碼放在背景工作角色中。 此方法允許更簡單的編排程式碼。 無需修改程式碼,就能處理各種部署情境,例如藍綠部署。