Durable Functions執行時會自動將函式參數、回傳值及其他狀態持續保存至 task hub,以確保執行可靠。 但保存至耐久性儲存體的資料數量和頻率,可能影響應用程式效能和儲存體交易成本。 根據應用程式存放區的資料類型,可能也需考慮資料保留和隱私權原則。
本文說明哪些資料會被持久保存、如何處理大型有效載重與敏感資料,以及如何針對每種支援語言自訂序列化。
本文內容:
任務中心內容
工作中樞會儲存執行個體的目前狀態和任何擱置的訊息:
-
執行個體狀態會儲存執行個體的目前狀態和歷程記錄。 針對協調流程執行個體,此狀態包含執行階段狀態、協調流程歷程記錄、輸入、輸出和自訂狀態。 針對實體執行個體,此會包含實體狀態。
-
訊息會儲存函式輸入或輸出、事件承載,以及用於內部用途 (路由和端對端關聯) 的中繼資料。
訊息會在處理之後刪除,但除非應用程式或操作員明確刪除訊息,否則仍會保存執行個體狀態。 特別是,流程編排的歷程記錄在流程編排完成後仍然保留在儲存體中。
如需狀態和訊息如何代表協調流程進度的範例,請參閱工作中樞執行範例。
儲存體中狀態和訊息顯示的位置和方式都取決於儲存體提供者。 使用 持久任務排程器 ,因為它為任務中心提供管理後端,並幫你處理底層的狀態儲存。 然而,Azure 儲存體 仍是現有工作負載及想要自行管理儲存資源的應用程式的穩健選擇。
| 儲存體提供者 |
狀態如何儲存 |
建議使用 |
| 持久性工作排程器 |
協調流程與實體狀態會存放在工作中樞資源後方的受控排程器後端。 |
新 Durable Functions 應用程式與託管部署的首選選項。 |
| Azure 儲存體 |
狀態與訊息會以佇列、資料表和 Azure 儲存體 帳號中的 blob 表示。 |
非常適合已經依賴 Azure 儲存體 的現有應用程式或部署。 |
序列化與持久化的資料類型
以下列表顯示使用 Durable Functions 功能時,將被序列化與持久化的不同資料類型:
- 協調器、活動和實體函式的所有輸入和輸出,包括任何識別碼和未處理的例外狀況
- 協調器、活動和實體函式名稱
- 外部事件名稱和承載
- 自訂協調流程狀態承載
- 協調流程終止訊息
- 耐久性計時器承載
- 耐久性 HTTP 要求與回應 URL、標頭和承載
- 實體呼叫和訊號承載
- 實體狀態載荷
關於管理有效載荷大小及保護本列表中敏感物品的指引,請參閱以下章節。
如果你提供大量輸入和輸出給 Durable Functions API,可能會遇到記憶體問題。 輸入與輸出會序列化於編排歷史中,這意味著大型有效載荷隨著時間推移,能大幅促進無界歷史成長。 這種成長有可能導致 重播時出現記憶異常。
為了減輕大量輸入與輸出的影響,您可以:
- 將工作委派給子編排器,以平衡多個編排器的歷史記憶體負擔,保持個別歷史的記憶體佔用量較小。
- 將大量資料儲存在外部儲存(例如 Azure Blob 儲存體),並傳遞輕量級識別碼,讓你在需要時能在活動函式中取得資料。
對於 Durable Task Scheduler,請利用大型有效載荷支援將較大的有效載荷卸載到 Azure Blob 儲存體。 對於新應用程式,當協調流程必須在持久性作業之間傳遞大型承載資料時,建議採用此模式。 如果你使用 Azure 儲存體 提供者,仍然可以套用以下章節所示的權利驗證模式,並在操作間傳遞輕量級參考。
Tip
處理大型資料的最佳做法是將其存放在外部儲存空間,並在需要時才在活動中實化這些資料。
傳遞大型承載的參照
選擇最適合你儲存服務提供者的圖案。
持久性工作排程器
如果你使用 Durable Task Scheduler,請啟用大型有效載荷支援,讓執行時將較大的有效載荷寫入 Azure Blob 儲存體,並透過排程器傳送一個小參考。 排程器文件中展示了典型的配置:
{
"version": "2.0",
"extensions": {
"durableTask": {
"storageProvider": {
"type": "azureManaged",
"connectionStringName": "DTS_CONNECTION_STRING",
"payloadStorageEnabled": true,
"payloadStorageThresholdBytes": 262144
},
"hubName": "%TASKHUB_NAME%"
}
}
}
Azure 儲存體
使用 Azure 儲存體 提供者時,您可以使用 Claim Check 模式,讓協調流程歷程維持精簡,同時仍可處理大型承載資料。 編排器會傳遞一個輕量參照,其中包含 Blob 容器與 Blob 名稱,而活動則會依需要從 Azure Blob 儲存體 讀取或寫入承載資料。
下列範例假設您的儲存體帳戶中已經有一個 Blob。 以參考資料開始編排,例如 {"container":"large-payloads","blobName":"input/job-123.json"}。 活動在必要時建立 processed-payloads 輸出容器。 取樣處理步驟會將輸入位元組不作更改地複製;用你的應用程式邏輯來取代它。
Important
參考中切勿包含儲存憑證或共享存取簽章(SAS)。 系統會將該參照保存在協調流程歷程記錄中。 這些範例使用了一個名為 PAYLOAD_STORAGE_CONNECTION_STRING App 的設定來保持儲存程式碼簡潔。 對於生產工作負載,請使用 Microsoft Entra ID 來授權對Blob 資料的存取。
這個範例需要 Azure。Storage.Blobs NuGet 套件。
using System;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
public record BlobReference(string Container, string BlobName);
public static class LargePayloadFunctions
{
[Function("ProcessLargePayload")]
public static async Task<BlobReference> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
BlobReference inputReference = context.GetInput<BlobReference>()
?? throw new InvalidOperationException("A blob reference is required.");
return await context.CallActivityAsync<BlobReference>(
nameof(ProcessLargePayloadActivity), inputReference);
}
[Function(nameof(ProcessLargePayloadActivity))]
public static async Task<BlobReference> ProcessLargePayloadActivity(
[ActivityTrigger] BlobReference inputReference)
{
string connectionString =
Environment.GetEnvironmentVariable("PAYLOAD_STORAGE_CONNECTION_STRING")
?? throw new InvalidOperationException("Payload storage is not configured.");
BlobServiceClient service = new BlobServiceClient(connectionString);
BlobClient inputBlob = service
.GetBlobContainerClient(inputReference.Container)
.GetBlobClient(inputReference.BlobName);
BinaryData inputData = (await inputBlob.DownloadContentAsync()).Value.Content;
BlobContainerClient outputContainer =
service.GetBlobContainerClient("processed-payloads");
await outputContainer.CreateIfNotExistsAsync();
string outputName = $"processed/{Guid.NewGuid():N}.json";
await outputContainer.GetBlobClient(outputName)
.UploadAsync(inputData, overwrite: true);
return new BlobReference(outputContainer.Name, outputName);
}
}
這個範例需要 Azure。Storage.Blobs NuGet 套件。
using System;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
public class BlobReference
{
public string Container { get; set; } = string.Empty;
public string BlobName { get; set; } = string.Empty;
}
public static class LargePayloadFunctions
{
[FunctionName("ProcessLargePayload")]
public static async Task<BlobReference> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
BlobReference inputReference = context.GetInput<BlobReference>()
?? throw new InvalidOperationException("A blob reference is required.");
return await context.CallActivityAsync<BlobReference>(
"ProcessLargePayloadActivity", inputReference);
}
[FunctionName("ProcessLargePayloadActivity")]
public static async Task<BlobReference> RunActivity(
[ActivityTrigger] BlobReference inputReference)
{
string connectionString =
Environment.GetEnvironmentVariable("PAYLOAD_STORAGE_CONNECTION_STRING")
?? throw new InvalidOperationException("Payload storage is not configured.");
BlobServiceClient service = new BlobServiceClient(connectionString);
BlobClient inputBlob = service
.GetBlobContainerClient(inputReference.Container)
.GetBlobClient(inputReference.BlobName);
BinaryData inputData = (await inputBlob.DownloadContentAsync()).Value.Content;
BlobContainerClient outputContainer =
service.GetBlobContainerClient("processed-payloads");
await outputContainer.CreateIfNotExistsAsync();
string outputName = $"processed/{Guid.NewGuid():N}.json";
await outputContainer.GetBlobClient(outputName)
.UploadAsync(inputData, overwrite: true);
return new BlobReference
{
Container = outputContainer.Name,
BlobName = outputName,
};
}
}
這個範例需要 @azure/storage-blob npm 套件。
const { randomUUID } = require("crypto");
const { BlobServiceClient } = require("@azure/storage-blob");
const df = require("durable-functions");
df.app.orchestration("processLargePayload", function* (context) {
const inputReference = context.df.getInput();
return yield context.df.callActivity(
"processLargePayloadActivity", inputReference);
});
df.app.activity("processLargePayloadActivity", {
handler: async (inputReference) => {
const connectionString =
process.env.PAYLOAD_STORAGE_CONNECTION_STRING;
if (!connectionString) {
throw new Error(
"PAYLOAD_STORAGE_CONNECTION_STRING is not set.");
}
const service = BlobServiceClient.fromConnectionString(
connectionString);
const inputBlob = service
.getContainerClient(inputReference.container)
.getBlockBlobClient(inputReference.blobName);
const inputData = await inputBlob.downloadToBuffer();
const outputContainer =
service.getContainerClient("processed-payloads");
await outputContainer.createIfNotExists();
const outputName = `processed/${randomUUID()}.json`;
await outputContainer.getBlockBlobClient(outputName)
.uploadData(inputData);
return {
container: outputContainer.containerName,
blobName: outputName,
};
},
});
這個範例需要 azure-storage-blob 套件。 加到 requirements.txt。
import os
import uuid
import azure.functions as func
import azure.durable_functions as df
from azure.core.exceptions import ResourceExistsError
from azure.storage.blob import BlobServiceClient
app = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)
@app.orchestration_trigger(context_name="context")
def process_large_payload(context: df.DurableOrchestrationContext):
input_reference: dict = context.get_input()
return (yield context.call_activity(
"process_large_payload_activity", input_reference))
@app.activity_trigger(input_name="input_reference")
def process_large_payload_activity(input_reference: dict) -> dict:
connection_string = os.getenv("PAYLOAD_STORAGE_CONNECTION_STRING")
if not connection_string:
raise ValueError(
"PAYLOAD_STORAGE_CONNECTION_STRING is not set.")
service = BlobServiceClient.from_connection_string(connection_string)
input_blob = service.get_blob_client(
container=input_reference["container"],
blob=input_reference["blobName"])
input_data = input_blob.download_blob().readall()
output_container = service.get_container_client("processed-payloads")
try:
output_container.create_container()
except ResourceExistsError:
pass
output_name = f"processed/{uuid.uuid4()}.json"
output_container.upload_blob(
name=output_name, data=input_data, overwrite=True)
return {
"container": output_container.container_name,
"blobName": output_name,
}
此範例需要 Az.Storage 模組。 將它新增至 requirements.psd1,並確認已在 host.json 中啟用受控相依性。
協調器 run.ps1:
param($Context)
$OutputReference = Invoke-DurableActivity `
-FunctionName 'ProcessLargePayloadActivity' `
-Input $Context.Input
return $OutputReference
活動:run.ps1
param($InputReference)
if ([string]::IsNullOrEmpty(
$env:PAYLOAD_STORAGE_CONNECTION_STRING)) {
throw 'The PAYLOAD_STORAGE_CONNECTION_STRING app setting is not configured.'
}
$StorageContext = New-AzStorageContext `
-ConnectionString $env:PAYLOAD_STORAGE_CONNECTION_STRING
$InputFile = New-TemporaryFile
try {
Get-AzStorageBlobContent `
-Container $InputReference.container `
-Blob $InputReference.blobName `
-Destination $InputFile.FullName `
-Context $StorageContext `
-Force | Out-Null
# Process $InputFile here. This example uploads it unchanged.
$OutputContainer = 'processed-payloads'
New-AzStorageContainer `
-Name $OutputContainer `
-Context $StorageContext `
-ErrorAction SilentlyContinue | Out-Null
$OutputName = "processed/$([guid]::NewGuid()).json"
Set-AzStorageBlobContent `
-File $InputFile.FullName `
-Container $OutputContainer `
-Blob $OutputName `
-Context $StorageContext `
-Force | Out-Null
return @{
container = $OutputContainer
blobName = $OutputName
}
}
finally {
Remove-Item $InputFile.FullName -Force
}
使用 Durable Functions 繫結中所述的標準 orchestrationTrigger 與 activityTrigger 繫結。
這個範例需要 com.azure:azure-storage-blob 和 com.microsoft:durabletask-azure-functions Maven 套件。
import com.azure.core.util.BinaryData;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.durabletask.TaskOrchestrationContext;
import com.microsoft.durabletask.azurefunctions.DurableActivityTrigger;
import com.microsoft.durabletask.azurefunctions.DurableOrchestrationTrigger;
import java.util.Objects;
import java.util.UUID;
public class LargePayloadFunctions {
public static class BlobReference {
public String container;
public String blobName;
public BlobReference() {
}
public BlobReference(String container, String blobName) {
this.container = container;
this.blobName = blobName;
}
}
@FunctionName("ProcessLargePayload")
public BlobReference runOrchestrator(
@DurableOrchestrationTrigger(name = "ctx")
TaskOrchestrationContext ctx) {
BlobReference inputReference = Objects.requireNonNull(
ctx.getInput(BlobReference.class),
"A blob reference is required.");
return ctx.callActivity(
"ProcessLargePayloadActivity",
inputReference,
BlobReference.class).await();
}
@FunctionName("ProcessLargePayloadActivity")
public BlobReference runActivity(
@DurableActivityTrigger(name = "inputReference")
BlobReference inputReference) {
String connectionString = Objects.requireNonNull(
System.getenv("PAYLOAD_STORAGE_CONNECTION_STRING"),
"PAYLOAD_STORAGE_CONNECTION_STRING is not configured.");
BlobServiceClient service = new BlobServiceClientBuilder()
.connectionString(connectionString)
.buildClient();
BinaryData inputData = service
.getBlobContainerClient(inputReference.container)
.getBlobClient(inputReference.blobName)
.downloadContent();
BlobContainerClient outputContainer =
service.getBlobContainerClient("processed-payloads");
outputContainer.createIfNotExists();
String outputName =
"processed/" + UUID.randomUUID() + ".json";
outputContainer.getBlobClient(outputName)
.upload(inputData, true);
return new BlobReference(
outputContainer.getBlobContainerName(), outputName);
}
}
若平行活動產生多個大型結果,則回傳一份參考清單,並將該清單傳給最終的聚合活動。 匯總活動應載入並合併承載,然後寫入一個最終輸出 blob。 不要在編排器中載入或串接大型結果。
處理敏感資料的工作
傳入與傳出 Durable Functions API 的輸入與輸出 (包括例外狀況) 會持久保存於您選擇的儲存體提供者中。 如果這些輸入、輸出或例外包含敏感資料(例如秘密、連線字串或個人識別資訊),任何擁有你儲存提供者資源讀取權限的人都可以取得這些資料。
為了安全處理敏感資料,請在活動函式中從 Azure Key Vault 或環境變數取得這些資料,且切勿直接與協調器或實體通訊這些資料。 此方法有助於防止敏感資料外洩至您的儲存資源。
同樣地,對儲存資源的寫入存取必須嚴格控制,因為儲存中被竄改的資料可能會改變編排行為。 欲了解更多關於確保任務中心儲存的安全資訊,請參閱 「保護您的任務中心儲存」。
Tip
此指引同樣適用於 CallHttp 編排器 API,該 API 會將其請求與回應有效載荷持續儲存。 如果你的目標 HTTP 端點需要認證,請在活動中實作 HTTP 呼叫,或使用 CallHttp 內建的管理身份支援,該支援不會將憑證持久化到儲存。
Note
避免記錄包含秘密的資料,因為任何有讀取權限的人(例如在 Application Insights)都可能取得這些秘密。
待用加密
使用 Azure 儲存體 提供者時,所有資料在靜止時會自動加密。 但有儲存體帳戶存取權時,任何使用者都可以未加密的格式讀取資料。 如果您需要更強大的敏感資料保護,請考慮先使用您自己的加密金鑰加密資料,然後資料會以預先加密的格式保存。
另外,.NET 使用者也可以選擇實作自訂序列化提供者,提供自動加密。 您可以在此 GitHub 範例中,找到使用加密的自訂序列化範例。
Note
如果您決定實作應用程式層級加密,請注意協調流程和實體可能無限期存在。 這在輪替加密金鑰時很重要,因為協調流程或實體的執行時間可能比金鑰輪替原則久。 如果發生金鑰輪替,下次執行協調流程或實體時,加密資料使用的金鑰可能無法再用於解密。 因此,只有在預期協調流程和實體執行時間相對較短時,才建議使用自訂加密。
保護你的任務中心儲存
承載你工作中心的儲存後端是關鍵的信任邊界。 持久任務框架信任它在編排重播與訊息處理過程中從儲存裝置讀取的資料。 任何擁有任務中心儲存寫入權限的人都可以干擾編排狀態、待處理訊息或儲存的有效載荷。 這可能會改變應用程式行為、觸發非預期動作,或在函式應用程式的情境中實現遠端程式碼執行。
Important
不要暴露你的任務中心儲存憑證,也不要授權寫入權限給不受信任的方。 對任務中心儲存的寫入權限可用來改變應用程式行為,包括觸發任意程式碼執行。
共同責任
保護儲存後端是你的責任,就像保護任何儲存應用程式狀態或程式碼的資料庫一樣。 耐用任務框架不對儲存資料進行完整性驗證,因此依賴儲存層的存取控制以防止未經授權的修改。
| Backend |
安全責任 |
指導方針 |
| 持久性工作排程器 |
Microsoft 負責管理底層的儲存後端。 你管理身份、任務中心存取權限,以及應用程式層級的安全。 |
新 Durable Functions 應用程式的慣用預設值。 |
| Azure 儲存體 及其他 BYO 供應商 |
你負責管理儲存帳號或資料庫及其安全控制。 |
非常適合已經依賴 Azure 儲存體 的工作負載或部署。 |
Note
不要在不信任的租戶之間共用任何一個工作中心。 工作中樞不會對其使用者強制執行存取界限,因此任何能讀取或寫入工作中樞的租用戶,都可影響其中所有的協調流程與實體。 同樣地,不要在同一後端用獨立的任務中心作為安全邊界。 雖然 Durable Task Scheduler 支援 針對個別任務集線器的 RBAC,但網路控制如 IP 允許清單和私有端點僅適用於排程器層級,因此排程器內的任務集線器並非安全隔離的邊界。 BYO 儲存服務提供者也是如此——任何擁有儲存帳號或資料庫存取權的租戶,都能存取該後端的所有任務中心。 當你需要租戶間的安全隔離時,為每個租戶配置獨立的基礎設施:為 BYO 提供者設置獨立的儲存帳號或資料庫,或是獨立的持久任務排程器實例。
儲存硬化檢查清單
請採用以下最佳實務來保護您的任務中心儲存空間:
針對您選擇的後端,使用以身分為基礎的連線。
- 使用持久任務排程器時,則依賴管理身份與 RBAC 來管理排程器與任務中心。
- 使用 Azure 儲存體 及其他 BYO 供應商時,盡可能偏好管理身份而非連接字串。
請參見 配置 Durable Functions 的管理身份。
套用最低權限的 RBAC 角色。 只授予所需的最低權限。 避免將廣泛儲存權限授予不需要的使用者或服務。
透過使用私有端點或服務端點,限制對儲存帳號或排程器部署的網路存取。 此限制有助於防止未經授權的網路層級存取任務集線中心資料。
監視儲存體存取,方法是啟用儲存體帳戶的 Azure 監視器 資源記錄,尤其是 StorageWrite 記錄類別。 將這些日誌路由到監控儲存帳號以外的目的地,例如 Log Analytics,這樣就不會被竄改。 請參閱 儲存日誌。
如果你使用連線字串,請定期輪換憑證。 對儲存帳戶金鑰的處理,請像對待其他高權限憑證一樣謹慎。
考慮管理式儲存後端。
Durable Task Scheduler 會自動處理儲存安全,包括認證、RBAC 和網路隔離,而 Azure 儲存體 則提供明確的儲存控制。
自訂序列化與反序列化
序列化的客製化選項因語言而異。 選擇您的語言標籤以查看可用選項。
預設序列化邏輯
適用於 .NET 的 Durable Functions 會在內部使用 Json.NET,將協調流程和實體資料序列化為 JSON。 預設使用的 Json.NET 設定如下:
輸入、輸出和狀態:
JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
DateParseHandling = DateParseHandling.None,
}
例外情況:
JsonSerializerSettings
{
ContractResolver = new ExceptionResolver(),
TypeNameHandling = TypeNameHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
}
如需詳細資訊,JsonSerializerSettings請參閱這裡。
以 .NET 屬性自訂序列化
在序列化過程中,Json.NET 會尋找類別和屬性上的 各種屬性,這些屬性控制資料如何從 JSON 序列化與反序列化。 如果你擁有傳給 Durable Functions API 的資料型別原始碼,可以考慮在型別中加入這些屬性,以自訂序列化和反序列化。
透過依賴注入來自訂序列化
以 .NET 為目標並在 Functions V3 執行階段上執行的函式應用程式,可以使用相依性插入 (DI) 自訂資料和例外狀況的序列化方式。 下列範例程式碼示範使用 IMessageSerializerSettingsFactory 和 IErrorSerializerSettingsFactory 服務介面的自訂實作時,如何使用 DI 覆寫預設 Json.NET 序列化設定。
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Collections.Generic;
[assembly: FunctionsStartup(typeof(MyApplication.Startup))]
namespace MyApplication
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton<IMessageSerializerSettingsFactory, CustomMessageSerializerSettingsFactory>();
builder.Services.AddSingleton<IErrorSerializerSettingsFactory, CustomErrorSerializerSettingsFactory>();
}
/// <summary>
/// A factory that provides the serialization for all inputs and outputs for activities and
/// orchestrations, as well as entity state.
/// </summary>
internal class CustomMessageSerializerSettingsFactory : IMessageSerializerSettingsFactory
{
public JsonSerializerSettings CreateJsonSerializerSettings()
{
// Return your custom JsonSerializerSettings here
}
}
/// <summary>
/// A factory that provides the serialization for all exceptions thrown by activities
/// and orchestrations
/// </summary>
internal class CustomErrorSerializerSettingsFactory : IErrorSerializerSettingsFactory
{
public JsonSerializerSettings CreateJsonSerializerSettings()
{
// Return your custom JsonSerializerSettings here
}
}
}
}
序列化和還原序列化邏輯
Azure Functions Node 應用程式使用JSON.stringify()執行序列化和JSON.Parse()還原序列化。 大部分的類型都會順利序列化和還原序列化。 當預設邏輯不足時,在 toJSON() 物件上定義方法會覆蓋序列化邏輯。 然而,對於物件反序列化並不存在類似的對應。
如需完整自訂序列化/還原序列化管道,請考慮使用您自己的程式碼處理序列化和還原序列化,並以字串的格式傳遞資料。
序列化和還原序列化邏輯
Durable Functions PowerShell 應用程式使用預設的 PowerShell JSON 處理來處理編排與活動有效載荷。 在大多數情況下,純 JSON 相容物件能正確序列化與反序列化,無需額外設定。
如果您需要針對承載資料結構採用自訂行為,請在函式內自行序列化或反序列化資料,並在協調器、活動和實體之間傳遞產生的、與 JSON 相容的值。 這種做法能明確顯示資料格式,避免依賴未暴露給 PowerShell 的序列化器自訂 API。
對於較複雜的情境,可以考慮將資料表示為簡單的字串、陣列或雜湊表,並在函式程式碼中轉換不同格式。
序列化和還原序列化邏輯
建議您使用類型註釋,確保 Durable Functions 正確將資料序列化和還原序列化。 還原序列化時,雖然會自動處理許多內建類型,但部分內建資料類型需要類型註釋,才能保留類型。
針對自訂數據類型,您可以藉由在數據類型類別中定義to_json和from_json類別方法,實現 JSON 的序列化與反序列化。 請注意,這些方法不會在協調器函式的傳回值上呼叫,這表示傳回值必須是原生 JSON 可序列化。 如需詳細資訊,請參閱 系結。
若要驗證反序列化的有效載體是否符合預期型別,並可選擇加入強化嚴格模式,請參見 Durable Functions for Python 中的「遷移至型別安全序列化」。
下一步