使用c#的 async/await编写 长时间运行的基于代码的工作流的 持久任务框架

   2023-02-09 学习力0
核心提示:持久任务框架 (DTF) 是基于async/await 工作流执行框架。工作流的解决方案很多,包括Windows Workflow Foundation,BizTalk,Logic Apps, Workflow-Core 和 Elsa-Core。最近我在Dapr 的仓库里跟踪工作流构建块的进展时,深入了解了一下,这个DTFx在Azure 基

持久任务框架 (DTF) 是基于async/await 工作流执行框架。工作流的解决方案很多,包括Windows Workflow Foundation,BizTalk,Logic Apps, Workflow-CoreElsa-Core。最近我在Dapr 的仓库里跟踪工作流构建块的进展时,深入了解了一下,这个DTFx在Azure 基础设施有大量的应用,现在Dapr团队正在把这个实践抽象成工作流构建块,具体参看https://github.com/dapr/dapr/issues/4576。DTFx 正好是.NET开发的,所以对他多了几分关注,以前没有深入进去看看,现在我觉得是值得推荐给大家的一个工作流方案,它足够轻量级,而且非常简单,依赖很少。

持久任务框架是一个开源框架,它为 .NET 平台中的工作流即代码提供了基础。GitHub上:https://github.com/Azure/durabletask

它有两个主要组件:业务流程和任务。业务流程“编排”应用程序逻辑,以内联方式执行自定义代码并调用任务。自定义业务流程派生自 TaskOrchestration<TResult, TInput>自定义任务派生自 TaskActivity<TInput, TResult>。

推荐大家从这两个仓库可用来学习和生产使用。

Microsoft.Extensions.Hosting包装器: https://github.com/jviau/durabletask-hosting

持久任务框架扩展: https://github.com/lucaslorentz/durabletask-extensions


我们一起来看下持久任务框架的Hello world: 代码来自https://github.com/jviau/durabletask-hosting 的 DurableTask.Samples:

这个非常简单的业务流程“GreetingsOrchestration”,有两个称为任务“GetUserTask”,它执行名称提示和“SendGreetingTask”,它将问候语写入控制台。

GreetingsOrchestration 派生自 TaskOrchestration<string、string> 并具有调用 GetUserTask 和 SendGreetingTask 的 RunTask 方法。

using DurableTask.Core;

namespace DurableTask.Samples.Greetings;

/// <summary>
/// A task orchestration for greeting a user.
/// </summary>
public class GreetingsOrchestration : TaskOrchestration<string, string>
{
     /// <inheritdoc />
     public override async Task<string> RunTask(OrchestrationContext context, string input)
     {
         string user = await context.ScheduleTask<string>(typeof(GetUserTask));
         string greeting = await context.ScheduleTask<string>(typeof(SendGreetingTask), user);
         return greeting;
     }
}

GetUserTask 派生自 TaskActivity<string,string> 并实现了 Execute 方法

using DurableTask.Core;

namespace DurableTask.Samples.Greetings;

/// <summary>
/// A task activity for getting a username from console.
/// </summary>
public class GetUserTask : TaskActivity<string, string>
{
     private readonly IConsole _console;

    /// <summary>
     /// Initializes a new instance of the <see cref="GetUserTask"/> class.
     /// </summary>
     /// <param name="console">The console output helper.</param>
     public GetUserTask(IConsole console)
     {
         _console = console ?? throw new ArgumentNullException(nameof(console));
     }

    /// <inheritdoc />
     protected override string Execute(TaskContext context, string input)
     {
         _console.WriteLine("Please enter your name:");
         return _console.ReadLine();
     }
}

SendGreetingTask 派生自 TaskActivity<string、string> 并实现了 Excute 方法

using DurableTask.Core;

namespace DurableTask.Samples.Greetings;

/// <summary>
/// A task for sending a greeting.
/// </summary>
public sealed class SendGreetingTask : AsyncTaskActivity<string, string>
{
     private readonly IConsole _console;

    /// <summary>
     /// Initializes a new instance of the <see cref="SendGreetingTask"/> class.
     /// </summary>
     /// <param name="console">The console output helper.</param>
     public SendGreetingTask(IConsole console)
     {
         _console = console ?? throw new ArgumentNullException(nameof(console));
     }

    /// <inheritdoc />
     protected override async Task<string> ExecuteAsync(TaskContext context, string user)
     {
         string message;
         if (!string.IsNullOrWhiteSpace(user) && user.Equals("TimedOut"))
         {
             message = "GetUser Timed out!!!";
             _console.WriteLine(message);
         }
         else
         {
             _console.WriteLine("Sending greetings to user: " + user + "...");
             await Task.Delay(5 * 1000);
             message = "Greeting sent to " + user;
             _console.WriteLine(message);
         }

        return message;
     }
}

上面的这个例子非常基础,我们在项目中要把它用起来就要用到这个扩展项目 https://github.com/lucaslorentz/durabletask-extensions。这个项目通过更多功能扩展持久任务框架,并使其更易于使用,目前还在开发过程中,尚未达到投入生产的程度。包含了下列这些功能,让你在任何地方都可以运行。

  • 更多定义存储功能的接口
  • 依赖注入集成
  • EF Core MySql/PostgreSQL/SqlServer storages
  • 分布式工作线程:允许在多个工作线程中拆分业务流程/活动实现
  • 通过 GRPC 协议进行间接存储访问:将您的存储选择和配置集中在单个组件中。
  • 用户界面
  • BPMN 运行器

示例文件夹中,您可以找到经典书籍《飞行、汽车、酒店》的实现,其中包含补偿问题。

该示例旨在演示具有以下组件的微服务体系结构:

  • 服务器:连接到存储并将其公开为 GRPC 终结点。
  • 应用程序接口:公开 REST API 以管理业务流程。
  • 用户界面:公开用于管理业务流程的 UI。
  • 业务流程工作线程:为给定问题实现BookParallelBookSquential业务流程。
  • 飞行工作人员:实施预订航班和取消航班活动。
  • 车夫:实施“预订汽车”和“取消汽车”活动。
  • 酒店工作人员:实施预订酒店和取消酒店活动。
  • BPMNWorker:一个建立在持久任务之上的实验性 BPMN 运行器。对于给定的问题,还有BookParallelBookSequentialBPMN 工作流。

image

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • VScode运行C++中文终端乱码的解决方案 vscode错误提示中文
    VScode运行C++中文终端乱码的解决方案 vscode错
    目录问题原因查看VSCODE编码方式查看终端编码方式解决办法更改VSCODE编码方式选通过编码保存选择编码方式为gbk总结问题Vscode编辑器中中文显示正常F5调试运行后中文显示乱码原因原因是VSCODE编辑器的编码和终端的编码不一致。VSCODE为utf-8,而cmd的默认编码
    03-08
  • C++ LeetCode1945题解字符串转化后的各位数字之和
    C++ LeetCode1945题解字符串转化后的各位数字
    目录1945.字符串转化后的各位数字之和方法一:计算AC代码C++1945.字符串转化后的各位数字之和力扣题目链接:leetcode.cn/problems/su…给你一个由小写字母组成的字符串 s ,以及一个整数 k 。首先,用字母在字母表中的位置替换该字母,将 s 转化 为一个整数(
  • C++ sdl实现渲染旋转视频的方法分享
    C++ sdl实现渲染旋转视频的方法分享
    目录前言一、如何实现1、计算边框大小2、计算缩放大小3、逆运算视频宽高二、完整代码三、使用示例总结前言一般情况下播放视频时不需要旋转,但是如果是移动端录制的视频有时会出现rotate参数,且视频宽高也是互换的,如果直接渲染则会出现视频90度倒转的问题
  • C++ LeetCode0547题解省份数量图的连通分量
    C++ LeetCode0547题解省份数量图的连通分量
    目录LeetCode 547.省份数量方法一:BFS求图的连通分量AC代码C++LeetCode 547.省份数量力扣题目链接:leetcode.cn/problems/nu…有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城
  • C++ LeetCode1832题解判断句子是否为全字母句
    目录LeetCode 1832.判断句子是否为全字母句方法一:统计AC代码C++LeetCode 1832.判断句子是否为全字母句力扣题目链接:leetcode.cn/problems/ch…全字母句 指包含英语字母表中每个字母至少一次的句子。给你一个仅由小写英文字母组成的字符串 sentence ,请
  • C++ LeetCode1781题解所有子字符串美丽值之和
    C++ LeetCode1781题解所有子字符串美丽值之和
    目录LeetCode 1781.所有子字符串美丽值之和方法一:前缀和AC代码C++方法二:边遍历边计算AC代码C++LeetCode 1781.所有子字符串美丽值之和力扣题目链接:leetcode.cn/problems/su…一个字符串的 美丽值 定义为:出现频率最高字符与出现频率最低字符的出现次
  • C++ LeetCode300最长递增子序列
    C++ LeetCode300最长递增子序列
    目录LeetCode 300.最长递增子序列方法一:动态规划AC代码C++LeetCode 300.最长递增子序列力扣题目链接:leetcode.cn/problems/lo…给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元
  • C++ LeetCode1780判断数字是否可以表示成三的幂的和
    C++ LeetCode1780判断数字是否可以表示成三的
    目录LeetCode 1780.判断一个数字是否可以表示成三的幂的和方法一:二进制枚举题目分析解题思路复杂度分析AC代码C++方法二:进制转换AC代码C++LeetCode 1780.判断一个数字是否可以表示成三的幂的和力扣题目链接:leetcode.cn/problems/ch…给你一个整数 n 
  • C++使用宏实现动态库加载 c++加载静态库
    目录前言一、为什么使用宏1、Windows加载2、Linux加载3、宏加载二、具体实现三、如何使用1、引用头文件2、添加导入宏3、直接调用总结前言开发的时候,有些项目不能静态链接动态库,需要程序运行时加载动态库,这个时候根据不同平台我们通常使用LoadLibrary或d
  • C++ LeetCode1805字符串不同整数数目
    目录LeetCode 1805.字符串中不同整数的数目方法一:遍历拆分AC代码C++LeetCode 1805.字符串中不同整数的数目力扣题目链接:leetcode.cn/problems/nu…给你一个字符串 word ,该字符串由数字和小写英文字母组成。请你用空格替换每个不是数字的字符。例如,"a12
点击排行