ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dapr 1.15.7 补丁详解:Workflow 定时启动失效与 DynamoDB 状态存储兼容性修复

Dapr 1.15.7 补丁详解:Workflow 定时启动失效与 DynamoDB 状态存储兼容性修复 Dapr 1.15.7 补丁详解Workflow 定时启动失效与 DynamoDB 状态存储兼容性修复【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/daprDapr 1.15.7 是 1.15 系列的一个纯维护补丁全部改动集中于 Dapr Workflow工作流引擎的两处缺陷Workflow 的Start Time定时启动功能失效以及使用 DynamoDB 作为工作流状态存储时无法运行工作流。本文以官方发布说明为骨架结合当前仓库中工作流引擎与状态存储注册的源码实现逐条还原两个问题的现象、根因与修复方式帮助读者理解 Dapr Workflow 的定时调度与状态持久化机制并为升级与排障提供依据。一、版本概览一次聚焦 Workflow 可靠性的补丁发布发布说明 docs/release_notes/v1.15.7.md 明确列出本次更新仅包含两项 bug 修复Fix Workflow Start TimeWorkflow 的定时启动功能失效Fix use of DynamoDB as Workflow state storeDynamoDB 无法作为 Workflow 状态存储使用。两个问题都指向 Dapr Workflow 的核心执行路径调度Scheduling与状态持久化State Persistence。理解这两处修复需要先了解 Dapr Workflow 的底层运行模型每一个工作流实例在 Dapr 内部都对应一个Actor 实例工作流的执行由 Actor 的Reminder提醒器驱动工作流的执行历史则持久化在被标记为 Actor 状态存储的组件中。这两条链路分别对应本次两个补丁。二、修复一Workflow Start Time定时启动失效2.1 问题现象与影响发布说明描述如下Problem使用 Workflow 的 Start Time 功能会导致工作流立即启动而不是在指定时间点启动Impact工作流无法被调度到未来的某个时间点再开始执行Root causeStart Time 没有被传递到负责执行工作流实例的 Actor ReminderSolution正确地将 Workflow 的 Start Time 传播到负责执行工作流实例的 Actor Reminder。简单说用户期望定时启动如schedule_start场景时工作流会在未来某个时间点被唤醒执行但在 1.15.7 之前的版本中工作流创建后立刻就被执行了定时功能形同虚设。2.2 根因分析Start Time 未传导至 Actor Reminder从源码看Dapr Workflow 的定时启动依赖的是工作流 Actor 的启动 Reminderstart reminder。关键逻辑位于pkg/actors/targets/workflow/common/pendingstart/pendingstart.go// DueTime is when the start reminder for an ExecutionStarted event is due: // its scheduled start when set, else the event timestamp. func DueTime(startEvent *backend.HistoryEvent) time.Time { if ts : startEvent.GetExecutionStarted().GetScheduledStartTimestamp(); ts ! nil { return ts.AsTime() } return startEvent.GetTimestamp().AsTime() }这段代码定义了启动 Reminder 的到期时间due time的计算规则若ExecutionStartedEvent携带了ScheduledStartTimestamp即用户设置的 Start Time则以该时间作为 Reminder 的到期时间否则回退到事件本身的Timestamp即立即执行。在创建工作流的链路上pkg/actors/targets/workflow/orchestrator/create.go的scheduleWorkflowStart先把启动事件ExecutionStarted写入 Actor 的 inbox事件队列并持久化再调用assertStartReminder创建唤醒 Reminderstate.KeepCreationInput(startEvent.GetExecutionStarted()) state.AddToInbox(startEvent) if err : o.signAndSaveState(ctx, state); err ! nil { return err } return o.assertStartReminder(ctx, startEvent)而assertStartReminder位于pkg/actors/targets/workflow/orchestrator/reminder.go正是将 Start Time 落成 Reminder 到期时间的关键一步func (o *orchestrator) assertStartReminder(ctx context.Context, startEvent *backend.HistoryEvent) error { start : pendingstart.DueTime(startEvent) workflowName : startEvent.GetExecutionStarted().GetName() reminderName : events.EventReminderName(reminderPrefixStart, startEvent) if err : o.createWorkflowReminder(ctx, reminderName, nil, start, o.appID, workflowName); err ! nil { o.armDetachedOnCreateError(reminderName, start, workflowName, startStillPending(reminderName), err) return err } o.localDrive(reminderName, start, workflowName) return nil }可以看到createWorkflowReminder的到期时间参数start完全来自pendingstart.DueTime(startEvent)。因此只要ScheduledStartTimestamp在创建请求中没能正确写入ExecutionStartedEvent或写入后未在创建链路中被保留DueTime就会回退到立即的事件时间戳工作流随即被 Reminder 立即唤醒——这正是发布说明描述的Start Time 未传播到 Actor Reminder的根因。1.15.7 的修复即是在这条链路上确保 Start Time 从用户请求一直传递到启动 Reminder 的到期时间。2.3 定时启动的完整链路与测试佐证综合 create.go 与 reminder.go一个定时启动的工作流从创建到执行的完整链路是客户端提交工作流创建请求其中携带期望的启动时间对应ScheduledStartTimestampscheduleWorkflowStart将ExecutionStartedEvent追加到 Actor inbox 并先持久化save-first防止 Reminder 先于状态落盘触发导致实例悬挂assertStartReminder依据pendingstart.DueTime计算 Reminder 到期时间即工作流的定时启动时间到点后 Reminder 触发工作流 Actor 被唤醒从持久化状态中加载 inbox 事件并开始执行编排逻辑。为了验证Reminder 到期时间必须遵守 ScheduledStartTimestamp仓库中的测试pkg/actors/targets/workflow/orchestrator/create_test.go专门设计了Test_scheduleWorkflowStart_honorsScheduledStartTimestamp第 211 行起测试先构造一个ScheduledStartTimestamp指向未来时刻的启动事件再断言调度出来的启动 Reminder 到期时间与定时时间一致从而锁死定时启动不被立即执行这一行为。此外pendingstart包还提供了Overdue判断与redrive补偿机制若实例已持久化但启动 Reminder 因故障丢失如创建中途崩溃状态读取路径会依据DueTime重新断言 Reminder保证定时启动在异常场景下也能被补驱动见 pendingstart.go 中的RedriveGrace与Overdue实现。三、修复二DynamoDB 无法作为 Workflow 状态存储3.1 问题现象与影响发布说明描述如下Problem使用 DynamoDB 作为 Workflow 状态存储时尝试运行工作流会报错Impact使用 DynamoDB 作为状态存储时工作流完全无法运行Root cause状态存储实现使用 StringS属性而非 BinaryB属性来存取数据导致状态无法被读取Solution更新 DynamoDB 状态存储实现改用 BinaryB属性存储工作流状态。3.2 根因分析S 属性与 B 属性的数据类型错配DynamoDB 的 AttributeValue 支持多种数据类型其中与本问题直接相关的是SStringUTF-8 编码的字符串BBinary任意二进制字节序列。而 Dapr Workflow 的状态天然是二进制数据。从 pkg/runtime/wfengine/state/state.go 可以看到工作流状态被组织为若干带前缀的键inbox、history、sigcert、ext-sigcert、signature、customStatus、metadata等每个键的值都是通过proto.Marshal序列化出来的protobuf 二进制字节随后通过TransactionalRequest一次性 upsert/delete 到 Actor 状态存储中对应GetSaveRequest方法。protobuf 二进制串并非总是合法 UTF-8 文本因此若用SString属性存取这类字节DynamoDB 客户端/服务端在编解码时无法保证字节级不变UTF-8 语义与二进制字节流存在映射差异写入后再读取会出现数据损坏或无法解析最终表现为状态不可读、运行工作流报错使用BBinary属性则能原样保存任意字节保证 protobuf 序列化数据完整往返。1.15.7 的修复即把 DynamoDB 状态存储实现中写入/读取工作流状态的属性类型从 S 改为 B从根本上消除了二进制数据经字符串属性中转的损坏风险。3.3 实现位置与版本依赖DynamoDB 状态存储组件在 Dapr 仓库中的注册入口位于 cmd/daprd/components/state_aws_dynamodb.goimport ( github.com/dapr/components-contrib/state/aws/dynamodb stateLoader github.com/dapr/dapr/pkg/components/state ) func init() { stateLoader.DefaultRegistry.RegisterComponent(dynamodb.NewDynamoDBStateStore, aws.dynamodb) }即组件类型名为aws.dynamodb其具体实现位于 Dapr 官方组件库 components-contrib本仓库通过 go.mod 以依赖形式固定其版本因此本次修复是随 components-contrib 的更新进入 1.15.7 的。Dapr 1.15.7 用户升级后aws.dynamodb状态存储即默认采用 Binary 属性读写工作流状态。3.4 Workflow 状态存储的配置要求值得注意的是并非所有状态存储都能直接用于 Workflow。Dapr Workflow 的后端构建在 Actor 运行时之上见 pkg/runtime/wfengine/backends/actors/actors.go其requireActorStateStore方法明确要求存在被指定为 Actor 状态存储的组件否则工作流操作会直接失败func (abe *Actors) requireActorStateStore() error { if _, _, ok : abe.compStore.GetStateStoreActor(); !ok { return messages.ErrActorRuntimeNotFound } return nil }将某个状态存储指定为 Actor 状态存储的标准方式是在组件配置的 metadata 中设置actorStateStore: true。一个典型的aws.dynamodb工作流状态存储配置示例如下apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore spec: type: state.aws.dynamodb version: v1 metadata: - name: table value: dapr-workflow-state - name: region value: us-west-2 - name: actorStateStore value: true仓库内的端到端测试配置如 tests/config/dapr_cosmosdb_state_actorstore.yaml也印证了这种使用模式为工作流应用workflowsapp及其 Actor 类型配置的 Actor 状态存储是独立组件Workflow 与普通 Actor 共享同一套 Actor 状态存储体系。因此若你的生产环境正在使用 DynamoDB 承载工作流请确认该组件已开启actorStateStore并升级到包含本次修复的版本。四、升级建议与验证方法升级路径本次为 1.15 系列的维护补丁建议所有 1.15.x 用户升级至 1.15.7若你在 1.15.x 中遇到了工作流无法定时启动或DynamoDB 状态存储运行工作流报错该版本即为对应修复。验证定时启动创建工作流时设置一个未来时刻的 Start Time观察工作流在到达该时间点之前应保持 Pending待启动状态到达后才开始执行并推进到 Running 状态单元测试Test_scheduleWorkflowStart_honorsScheduledStartTimestamp覆盖了该行为。验证 DynamoDB 状态存储以 DynamoDB 为 Actor 状态存储创建并运行一个简单工作流确认创建、活动执行、完成各阶段不再报状态读取错误可结合工作流状态表中历史/元数据行的读写结果确认二进制数据完整往返。总结Dapr 1.15.7 虽小却覆盖了 Workflow 引擎两个最关键的运行面时间调度与持久化。前者修复了定时启动在 Actor Reminder 链路中的传递丢失后者修复了 DynamoDB 对二进制 protobuf 状态数据的属性类型错配。理解这两处修复也就理解了 Dapr Workflow 依赖 Actor Reminder 驱动执行、依赖 Actor 状态存储持久化历史的底层机制这对后续排查工作流类问题同样具有直接参考价值。【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表