ABP VNext + Elsa Workflow:实现可视化流程引擎
🚀 ABP VNext + Elsa Workflow:实现可视化流程引擎 🎉
📚 目录
- 1. 背景与动机 🤔
- 2. 核心技术点 🌟
- 2.1 安装所需 NuGet 包 📦
- 2.2 ABP Module 中集成 Elsa 🔗
- 2.3 Workflow Definition DSL 📝
- 2.4 自定义 Activity 示例 ⚙️
- 2.5 持久化、审计与监控 📊
- 2.5.1 EF Core 迁移 🛠️
- 2.5.2 审计日志关联 📝
- 2.5.3 Prometheus & Grafana 📈
- 3. 实战演示:“请假审批”流程 🚀
- 4. 优化指南 🔧
- 4.1 配置分层与安全 🔒
- 4.2 异常处理与超时 ⏱️
- 4.3 单元测试 & 端到端测试 🧪
- 4.4 版本兼容与升级路线 🚀
- 4.5 健康检查与日志聚合 🏥
1. 背景与动机 🤔
在大型企事业单位中,请假、报销、工单等审批流程往往跨越多部门、多层级,硬编码实现难以维护。
可视化流程引擎 能让业务人员通过拖拽定义流程,开发人员只需聚焦节点扩展与平台集成。
2. 核心技术点 🌟
2.1 安装所需 NuGet 包 📦
dotnet add package Elsa.Workflows.Core
dotnet add package Elsa.Activities.Http
dotnet add package Elsa.Activities.Console
dotnet add package Elsa.Activities.UserTask
dotnet add package Elsa.Persistence.EntityFramework.Core
dotnet add package Elsa.Persistence.EntityFramework.PostgreSql
dotnet add package Elsa.Metrics.Prometheus
dotnet add package Microsoft.EntityFrameworkCore.Design
如需其他数据库,替换对应的 EF 提供器包即可。
2.2 ABP Module 中集成 Elsa 🔗
[DependsOn(typeof(AbpAspNetCoreMvcModule),typeof(AbpDistributedLockingModule)
)]
public class MyCompanyWorkflowModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){var configuration = context.Services.GetConfiguration();context.Services.AddElsa(elsa => elsa// 持久化配置.UseEntityFrameworkPersistence(ef => ef.UseNpgsql(configuration.GetConnectionString("Default")).UseJsonSerializer().UseTablePrefix("Elsa_"))// 内置活动.AddConsoleActivities().AddHttpActivities(ops => ops.WithClientFactory("RetryClient", client => client.ConfigureHttpClient(c => c.Timeout = TimeSpan.FromSeconds(10)).AddPolicyHandler(Policy.Handle<HttpRequestException>().WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(2)))))// 自定义活动.AddActivity<SendNotificationActivity>()).AddElsaApiEndpoints();}
}
2.3 Workflow Definition DSL 📝
{"Activities": [{ "Type": "Elsa.Activities.Http.HttpEndpoint", "Id": "start","Properties": { "Path": "/api/workflows/leave", "Method": "POST" } },{ "Type": "Elsa.Activities.UserTask.UserTask", "Id": "deptApproval","Properties": { "Title": "部门审批" } },{ "Type": "Elsa.Activities.UserTask.UserTask", "Id": "hrApproval","Properties": { "Title": "HR 审批" } },{ "Type": "Elsa.Activities.Http.HttpResponse", "Id": "end","Properties": { "Content": "审批完成" } }],"Connections": [{ "Source": "start", "Target": "deptApproval" },{ "Source": "deptApproval", "Target": "hrApproval" },{ "Source": "hrApproval", "Target": "end" }]
}
Elsa 2.3+ 支持
Connections
,低版本请参考Outcome
。
2.4 自定义 Activity 示例 ⚙️
public class SendNotificationActivity : Activity
{private readonly ILogger<SendNotificationActivity> _logger;public SendNotificationActivity(ILogger<SendNotificationActivity> logger) =>_logger = logger;protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context){try{var dto = context.GetInput<LeaveRequest>();var notifier = context.ServiceProvider.GetRequiredService<INotificationPublisher>();notifier.PublishAsync("LeaveApproved", dto);return Done();}catch (Exception ex){_logger.LogError(ex, "通知发送失败");return Fault(ex);}}
}
2.5 持久化、审计与监控 📊
2.5.1 EF Core 迁移 🛠️
dotnet ef migrations add Elsa_Init -c ElsaContext -o Migrations/Elsa
dotnet ef database update -c ElsaContext
2.5.2 审计日志关联 📝
Configure<AbpAuditingOptions>(options =>
{options.EntityHistorySelectors.Add<WorkflowInstance>(selector =>selector.Include(x => x.Id).Include(x => x.Status).Include(x => x.Variables));
});
2.5.3 Prometheus & Grafana 📈
services.AddElsaMetrics(metrics => metrics.AddPrometheus());
// appsettings.Production.json
{"Metrics": {"Prometheus": {"Enabled": true}}
}
# prometheus.yml
scrape_configs:- job_name: 'elsa'static_configs:- targets: ['localhost:5000']
3. 实战演示:“请假审批”流程 🚀
[Authorize]
[ApiController]
[Route("api/workflows")]
public class LeaveController : ControllerBase
{private readonly IWorkflowRunner _workflowRunner;public LeaveController(IWorkflowRunner workflowRunner) =>_workflowRunner = workflowRunner;[HttpPost("leave")]public async Task<IActionResult> StartLeaveWorkflow([FromBody] LeaveRequest dto){var wfInstance = await _workflowRunner.TriggerAsync("LeaveWorkflow", new Variables(dto));return Ok(new { WorkflowInstanceId = wfInstance.Id });}
}
4. 优化指南 🔧
4.1 配置分层与安全 🔒
- 分层管理:将连接串、Prometheus 配置分别放在
appsettings.Development.json
/appsettings.Production.json
,并通过IConfiguration.GetSection(...)
读取。 - Secret 管理:生产环境使用环境变量、Azure Key Vault 或 HashiCorp Vault 管理敏感信息,避免硬编码。
4.2 异常处理与超时 ⏱️
- 在自定义 Activity 中捕获异常并返回
Fault(ex)
。 - 在 HTTP 活动中通过
ConfigureHttpClient(c => c.Timeout = ...)
设置超时,结合 Polly 实现重试。
4.3 单元测试 & 端到端测试 🧪
[Fact]
public void SendNotificationActivity_Should_Done()
{var services = new ServiceCollection().AddSingleton<INotificationPublisher, FakePublisher>().BuildServiceProvider();var context = new ActivityExecutionContext(/*...*/, services);var activity = new SendNotificationActivity(services.GetService<ILogger<SendNotificationActivity>>());var result = activity.OnExecute(context);Assert.IsType<DoneResult>(result);Assert.True(((FakePublisher)services.GetService<INotificationPublisher>()).WasCalled);
}
端到端测试可使用 InMemoryProvider 启动流程,验证各节点执行顺序与结果。
4.4 版本兼容与升级路线 🚀
- Elsa v3 预览:关注 JSON 架构、API 调用变化。
- ABP 升级:小版本间 DI、Module 生命周期可能有细微差异,建议锁定兼容范围。
4.5 健康检查与日志聚合 🏥
services.AddHealthChecks().AddDbContextCheck<ElsaContext>("Elsa DB").AddCheck<CustomQueueHealthCheck>("消息队列");
使用 Serilog + Seq/ELK 汇总 Elsa 运行时日志,便于异常排查。