ABP VNext + Dapr Workflows:輕量級分布式工作流

🚀 ABP VNext + Dapr Workflows:輕量級分布式工作流


📚 目錄

  • 🚀 ABP VNext + Dapr Workflows:輕量級分布式工作流
    • 一、引言 ?
      • TL;DR 🔥
    • 二、環境與依賴 🛠?
    • 三、系統架構與流程圖 🏗?
    • 四、在 ABP 模塊中注冊 Dapr Workflows 📦
    • 五、定義 Workflow 與 Activities 🎯
      • 5.1 定義活動(Activity)
      • 5.2 定義工作流(Workflow)
    • 六、觸發與查詢工作流 🔍
      • 6.1 啟動 ABP 應用
      • 6.2 發起工作流
      • 6.3 暴露查詢端點
    • 七、示例演示 🎬
    • 八、最佳實踐與優化 💡


一、引言 ?

TL;DR 🔥

  • 在 ABP VNext 應用中,只需一行 services.AddDaprWorkflow(...) 即可無侵入集成 Dapr Workflow SDK,開啟長運行分布式工作流編排 🎉 (Dapr Docs)
  • 通過 state.redis 或 CosmosDB 等可插拔 State Store 實現跨服務狀態持久化與恢復,支持 Saga 補償模式 🔄 (Dapr Docs)
  • 定義繼承自 Workflow<TInput, TOutput> 的工作流類與 WorkflowActivity<TArg, TResult> 的活動類,使用 context.CallActivityAsync 保證確定性重放 🛠? (Diagrid)
  • 演示“下單—保留庫存—扣款—失敗補償”全流程,涵蓋高性能、高可用、易復現實踐 ?

背景
在微服務架構中,分布式事務難以擴展,“最終一致性”與 Saga 模式已成主流。Dapr Workflows 提供代碼化工作流,基于 DurableTask 引擎在 State Store 中持久化狀態,結合補償與定時器,簡化復雜業務的可靠編排。


二、環境與依賴 🛠?

  • .NET 平臺:.NET 9,ABP vNext v9.x

  • Dapr 運行時:Dapr CLI ≥1.10;Workflow Runtime v1.15.4

  • NuGet 包

    dotnet add package Dapr.Workflow --version 1.15.4
    
  • State Store 組件 (components/statestore.yaml):

    apiVersion: dapr.io/v1alpha1
    kind: Component
    metadata:name: statestore
    spec:type: state.redisversion: v1metadata:- name: redisHostvalue: "localhost:6379"# 生產環境推薦使用支持事務的后端,如 Azure Cosmos DB 或 SQL Server
    

    (Dapr Docs)

  • 基礎設施:Redis / Azure Cosmos DB;Dapr Sidecar


三、系統架構與流程圖 🏗?

State_Store
Workflow_Runtime
ABP_App
ScheduleNewWorkflowAsync
Redis/CosmosDB
OrderWorkflow 實例
ReserveInventoryActivity
ChargePaymentActivity
RefundPaymentActivity
ReleaseInventoryActivity
Dapr Sidecar
OrderService API
  • OrderService API 通過 Dapr Sidecar 調用 Workflow 管理 API
  • Workflow Runtime 調度活動并將狀態寫入 State Store,支持斷點重放
  • Saga 補償:在失敗場景通過補償活動保證最終一致性

四、在 ABP 模塊中注冊 Dapr Workflows 📦

using Dapr.Client;
using Dapr.Workflow;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;public class MyAppModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){// 可選:顯式注冊 DaprClientcontext.Services.AddDaprClient();// 一行集成 Dapr Workflows,自動注冊 Client 與 Workercontext.Services.AddDaprWorkflow(options =>{options.RegisterWorkflow<OrderWorkflow>();options.RegisterActivity<ReserveInventoryActivity>();options.RegisterActivity<ChargePaymentActivity>();options.RegisterActivity<RefundPaymentActivity>();options.RegisterActivity<ReleaseInventoryActivity>();});}
}

AddDaprWorkflow 會自動注冊 DaprWorkflowClientDaprClient(若未注冊)及后臺 HostedService,無需額外中間件調用 (Dapr Docs)


五、定義 Workflow 與 Activities 🎯

using Dapr.Workflow;
using Dapr.Workflow.Models;

5.1 定義活動(Activity)

繼承自 WorkflowActivity<TArg, TResult> 并重寫 RunAsync,實現冪等邏輯:

public record PaymentInput(Guid OrderId, decimal Amount);public class ReserveInventoryActivity : WorkflowActivity<Guid, bool>
{public override Task<bool> RunAsync(WorkflowActivityContext context,Guid orderId){// 調用庫存服務,保證冪等return Task.FromResult(true);}
}public class ChargePaymentActivity : WorkflowActivity<PaymentInput, bool>
{public override Task<bool> RunAsync(WorkflowActivityContext context,PaymentInput input){// 調用支付服務,保證冪等return Task.FromResult(true);}
}

(Diagrid)

5.2 定義工作流(Workflow)

繼承自 Workflow<OrderDto, object>,在 RunAsync 中編排活動并處理補償:

public class OrderWorkflow : Workflow<OrderDto, object>
{public override async Task<object> RunAsync(WorkflowContext context,OrderDto order){var logger = context.CreateReplaySafeLogger<OrderWorkflow>();logger.LogInformation("Order {OrderId} 開始", order.Id);try{await context.CallActivityAsync<bool>(nameof(ReserveInventoryActivity),order.Id);await context.CallActivityAsync<bool>(nameof(ChargePaymentActivity),new PaymentInput(order.Id, order.Amount));}catch (Exception ex){logger.LogWarning(ex, "執行失敗,開始補償");await context.CallActivityAsync<bool>(nameof(RefundPaymentActivity),order.Id);await context.CallActivityAsync<bool>(nameof(ReleaseInventoryActivity),order.Id);throw;}logger.LogInformation("Order {OrderId} 完成", order.Id);return null!;}
}

(Diagrid)


六、觸發與查詢工作流 🔍

6.1 啟動 ABP 應用

dapr run \--app-id order-api \--app-port 5000 \--dapr-http-port 3500 \--components-path ./components \dotnet run

6.2 發起工作流

using Dapr.Workflow;public class OrderAppService : ApplicationService
{public async Task<string> CreateOrderAsync(CreateOrderDto dto){var client = ServiceProvider.GetRequiredService<DaprWorkflowClient>();string instanceId = Guid.NewGuid().ToString();await client.ScheduleNewWorkflowAsync(workflowName: nameof(OrderWorkflow),instanceId: instanceId,input: dto);return instanceId;}// 新增:查詢工作流狀態public async Task<WorkflowState> GetWorkflowStateAsync(string instanceId){var client = ServiceProvider.GetRequiredService<DaprWorkflowClient>();return await client.GetWorkflowStateAsync(instanceId, includeInputsAndOutputs: true);}
}

使用 ScheduleNewWorkflowAsync 啟動實例 (Dapr Docs)

6.3 暴露查詢端點

using Dapr.Workflow;
using Microsoft.AspNetCore.Mvc;[ApiController]
[Route("api/workflows")]
public class WorkflowController : ControllerBase
{private readonly DaprWorkflowClient _client;public WorkflowController(DaprWorkflowClient client) => _client = client;[HttpGet("{instanceId}")]public async Task<IActionResult> Get(string instanceId){var state = await _client.GetWorkflowStateAsync(instanceId, includeInputsAndOutputs: true);return Ok(state);}
}
curl http://localhost:5000/api/workflows/{instanceId}
  • 返回 JSON 包含 RuntimeStatus、輸入輸出、歷史事件等信息。

七、示例演示 🎬

  1. 基礎設施

    docker run -d --name redis -p 6379:6379 redis
    dapr init --runtime-version v1.10
    
  2. 運行應用并發起訂單

    curl -X POST http://localhost:5000/api/orders \-H "Content-Type: application/json" \-d '{"productId":"123","quantity":1,"amount":100}'
    
  3. 查詢狀態

    curl http://localhost:5000/api/workflows/{instanceId}
    
  4. 模擬失敗:在 ChargePaymentActivity 拋出異常,驗證補償活動自動執行 💥


八、最佳實踐與優化 💡

  • 冪等性:活動內部調用盡量冪等,防止重試產生副作用。
  • 超時與重試:結合 Durable Timers 及 RetryOptions 控制超時與重試。
  • 并行與分支:可在工作流中使用 Task.WhenAll(...) 或動態 CallActivityAsync 實現并行。
  • 版本兼容:升級工作流時,通過前綴或遷移邏輯兼容老實例。
  • 生產環境:推薦使用支持事務回滾的 State Store(Cosmos DB、SQL Server)替代 Redis (Dapr Docs)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91884.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91884.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91884.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

? Unity 實現UI視差滾動效果(Parallax)鼠標控制、可拓展陀螺儀與腳本控制

? 效果如下在許多游戲、APP 或動效頁面中&#xff0c;我們常見的一種視覺效果是 視差滾動&#xff08;Parallax Scrolling&#xff09;&#xff1a;前景、中景、背景在鼠標或設備移動時以不同速率輕微移動&#xff0c;從而營造出一種空間感和深度感。目前遇到這樣一個需求 所以…

【05】VM二次開發——模塊參數配置--帶渲染/不帶渲染(WinForm界面調用 模塊參數配置)

文章目錄1 Winform 窗口界面 &#xff08;帶渲染的參數配置控件&#xff09;2 配置代碼3 運行測試4 不帶渲染的參數配置控件 對比4.1 添加控件4.2 代碼及演示效果模塊參數配置本教程介紹如何在VM二次開發中對模塊參數進行配置 1 Winform 窗口界面 &#xff08;帶渲染的參數配置…

Android 之 藍牙通信(2.0 經典)

??一、環境配置??1. ??添加依賴??在 build.gradle 中添加庫依賴&#xff1a;dependencies {implementation com.github.akexorcist:bluetoothspp:1.0.0 }2. ??權限聲明&#xff08;AndroidManifest.xml&#xff09;?<uses-permission android:name"androi…

使用 Scikit-LLM 進行零樣本和少樣本分類

使用 Scikit-LLM 進行零樣本和少樣本分類 使用 Scikit-LLM 進行零樣本和少樣本分類 在本文中&#xff0c;您將學習&#xff1a; Scikit-LLM如何將OpenAI的GPT等大型語言模型與Scikit-learn框架集成以進行文本分析。零樣本和少樣本分類之間的區別以及如何使用Scikit-LLM實現它…

android內存作假通殺補丁(4GB作假8GB)

可過如下app檢測&#xff1a; 安兔兔、魯大師、白眼、AIDA64、CPU X、CPU-Z、DevCheck、DeviceInfoHW lyw235yk235:~/Extend/lyw235/V/sprdroid1_v_4/sprdroid1_v$ git diff vnd/bsp/kernel5.15/kernel5.15/mm/page_alloc.c diff --git a/vnd/bsp/kernel5.15/kernel5.15/mm/pag…

Android 之 MVC架構

介紹1. MVC架構分工????Model層??&#xff1a;處理數據驗證、網絡請求等業務邏輯。??View層??&#xff1a;XML布局定義界面&#xff0c;Activity處理用戶輸入和顯示結果。??Controller層??&#xff1a;Activity作為控制器&#xff0c;協調Model和View的交互對于登…

Centos Docker 安裝手冊(可用)

Centos 安裝 Docker # 卸載舊版 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine \docker-selinux # 安裝依賴工具 yum install -y yum-utils device-mapper-persistent-d…

烽火HG680-KX-海思MV320芯片-2+8G-安卓9.0-強刷卡刷固件包

烽火HG680-KX-海思MV320芯片-28G-安卓9.0-強刷卡刷固件包U盤強刷刷機步驟&#xff1a;1、強刷刷機&#xff0c;用一個usb2.0的8G以下U盤&#xff0c;fat32&#xff0c;2048塊單分區格式化&#xff08;強刷對&#xff35;盤非常非常挑剔&#xff0c;usb2.0的4G U盤兼容的多&…

Python爬蟲實戰:研究pycares技術構建DNS解析系統

1. 引言 1.1 研究背景 隨著互聯網的飛速發展,網絡上的數據量呈現爆炸式增長。網絡爬蟲作為一種高效的數據采集工具,被廣泛應用于數據分析、市場調研、學術研究等領域。傳統的爬蟲在進行大規模數據采集時,往往會受到 DNS 解析效率的制約,成為影響爬取性能的瓶頸之一。 DNS…

從 0 到 1 認識 Spring MVC:核心思想與基本用法(下)

文章目錄&#x1f4d5;4. 響應??4.1 返回靜態頁面??4.2 返回數據ResponseBody???4.3 返回HTML代碼片段???4.4 返回JSON??4.5 設置狀態碼??4.6 設置Header&#xff08;了解&#xff09;&#x1f4d5;5. 案例練習??5.1 加法計算器??5.2 用戶登錄??5.3 留言板…

Python-初學openCV——圖像預處理(五)——梯度處理、邊緣檢測、圖像輪廓

目錄 一、圖像梯度處理 1、垂直邊緣提取 2、Sobel算子 3、Laplacian算子 二、圖像邊緣檢測 1、高斯濾波 2、計算圖像的梯度、方向 3、非極大值抑制 4、雙閾值篩選 三、繪制圖像輪廓 1、概念 2、尋找輪廓 3、繪制輪廓 一、圖像梯度處理 還記得高數中的一階導數求極值…

【Redis】安裝Redis,通用命令,常用數據結構,單線程模型

目錄 一.在Ubuntu系統安裝Redis 二. redis客戶端介紹 三. 全局命令 3.1.GET和SET命令 3.2.KEYS&#xff08;生產環境禁止使用&#xff09; 3.3.EXISTS 3.4.DEL 3.5.EXPIRE 3.6.TTL 3.6.1.Redis的過期策略 3.6.2.基于優先級隊列/堆的實現去實現定時器 3.6.3.定時器&a…

ubuntu22.04系統實踐 linux基礎入門命令(三) 用戶管理命令

以下有免費的4090云主機提供ubuntu22.04系統的其他入門實踐操作 地址&#xff1a;星宇科技 | GPU服務器 高性能云主機 云服務器-登錄 相關兌換碼星宇社區---4090算力卡免費體驗、共享開發社區-CSDN博客 之所以推薦給大家使用&#xff0c;是因為上面的云主機目前是免費使用的…

DPDK中的TCP頭部處理

1. TCP頭部結構 TCP頭部通常為20字節&#xff08;不含可選字段&#xff09;&#xff0c;每個字段占據固定的字節位置。以下是TCP頭部的結構&#xff0c;按字節位置逐一說明&#xff1a;0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 …

開源在線客服系統Chatwoot配置文件

參考&#xff1a; https://developers.chatwoot.com/self-hosted/deployment/dockerhttps://developers.chatwoot.com/self-hosted/deployment/docker 1、.env 配置文件 # Learn about the various environment variables at # https://www.chatwoot.com/docs/self-hosted/co…

PHP進階語法詳解:命名空間、類型轉換與文件操作

掌握了PHP面向對象編程的基礎后&#xff0c;就可以深入學習命名空間、類型轉換、文檔注釋、序列化以及文件操作等重要概念。 1、命名空間&#xff08;Namespace&#xff09; 命名空間是PHP 5.3引入的重要特性&#xff0c;它解決了類名、函數名和常量名沖突的問題&#xff0c;使…

Webpack 搭建 Vue3 腳手架詳細步驟

創建一個新的 Vue 項目 1&#xff09;初始化項目目錄 新建一個文件夾&#xff0c;或者使用以下指令 mkdir webpack-vue_demo cd webpack-vue_demo2&#xff09;初始化 npm 項目 npm init -y3&#xff09;安裝 vue 和 webpack 相關依賴 npm install vue vue-loader vue-template…

【Git 誤操作恢復指南】

Git 誤操作恢復指南 適用場景&#xff1a;git reset --hard 誤操作后的緊急恢復 風險等級&#xff1a;&#x1f534; 高風險 - 可能導致代碼丟失 恢復成功率&#xff1a;95%&#xff08;CI/CD 環境下&#xff09; &#x1f6a8; 緊急情況概述 問題描述 在項目開發過程中&am…

Go語言 逃 逸 分 析

逃逸分析是什么 逃逸分析是編譯器用于決定變量分配到堆上還是棧上的一種行為。一個變量是在堆上分配&#xff0c;還是在棧上分配&#xff0c;是經過編譯器的逃逸分析之后得出的“結論”。Go 語言里編譯器的逃逸分析&#xff1a;它是編譯器執行靜態代碼分析后&#xff0c…

LeetCode算法日記 - Day 1: 移動零、復寫零

目錄 1. 移動零 1.1 思路解析 1.2 代碼實現 2. 復寫零 2.1 思路解析 2.2 代碼實現 1. 移動零 283. 移動零 - 力扣&#xff08;LeetCode&#xff09; 給定一個數組 nums&#xff0c;編寫一個函數將所有 0 移動到數組的末尾&#xff0c;同時保持非零元素的相對順序。 請…