尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Dapr 1.6.3 补丁详解:修复无 Actor 状态存储时 Actor API 初始化失败的问题

Dapr 1.6.3 补丁详解:修复无 Actor 状态存储时 Actor API 初始化失败的问题 Dapr 1.6.3 补丁详解修复无 Actor 状态存储时 Actor API 初始化失败的问题【免费下载链接】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本指南围绕 Dapr 1.6.3 发布说明docs/release_notes/v1.6.3.md中记录的唯一一项修复展开当服务未配置 actor 状态存储组件时Actor API 在初始化阶段被错误地整体禁用导致仅作为客户端调用 Actor 的服务无法正常工作。阅读完本文你将理解该缺陷的根因、官方修复方案以及如何通过actorStateStore元数据标记与scopes隔离在真实项目中让纯 Actor 调用方与Actor 宿主两类服务正确共存。1. 问题背景所有 Actor API 都要求 actor 状态存储在 Dapr 的 Actor 模型中一个 Dapr 应用可以扮演两种截然不同的角色Actor 宿主host应用自身注册了 Actor 类型通过entities声明负责承载并执行这些 Actor持久化 Actor 状态、提醒reminders、定时器timers和工作流状态。此类服务必须配置 actor 状态存储组件否则无法工作。Actor 客户端client / invoker应用不注册任何 Actor 类型仅通过 Dapr 的 Actor APIHTTP/gRPC调用其他应用托管的 Actor例如编排层的聚合服务、网关或压测客户端。在 Dapr 1.6.3 之前daprd 初始化 Actor API 的逻辑存在一个缺陷只要组件列表中没有 actor 状态存储Actor API 的初始化就会直接报错完全不区分该服务到底是 Actor 宿主还是纯客户端。官方发布说明中对该问题的定义是All Actor APIs return errors without an actor state store component being provided. This is the correct behavior for services that register actors, as they require state storage, but clients that invoke actors should operate with or without an actor state store.也就是说对注册了 Actor 的服务要求状态存储是正确的但对仅调用 Actor 的客户端服务而言没有状态存储也应当能够正常启动并调用 Actor。旧行为把两类服务一概而论导致客户端服务在缺少 actor 状态存储时整个 Actor API 不可用。2. 根因分析初始化逻辑未区分是否注册 Actor发布说明指出的根因非常明确The code that initializes the Actor API raises an error when there is no actor state storage component available, regardless of whether or not the service registers actors.即负责初始化 Actor API 的代码在检测到没有可用的 actor 状态存储组件时一律返回错误并没有检查该服务是否实际注册了 Actor。虽然当前仓库已经历多个版本迭代但这段逻辑的演进脉络仍然清晰可见且与修复思路一脉相承。在 pkg/runtime/runtime.go 中initActors如今已把没有 actor 状态存储从硬错误降级为一条信息日志func (a *DaprRuntime) initActors(ctx context.Context) error { err : actors.ValidateHostEnvironment(a.runtimeConfig.mTLSEnabled, a.runtimeConfig.mode, a.namespace) if err ! nil { return rterrors.NewInit(rterrors.InitFailure, actors, err) } if _, ok : a.processor.State().ActorStateStoreName(); !ok { log.Info(actors: state store is not configured - actor state and workflow operations will be unavailable until an actor state store component is loaded) } // ... if err : a.actors.Init(actors.InitOptions{ ... }); err ! nil { return err } return nil }对照测试 pkg/runtime/runtime_test.go 中的用例 the actor store can not be initialized normally可以看到该行为已被固定为即使ActorStateStoreName()返回false没有 actor 状态存储initActors仍然成功返回、不报错name, ok : r.processor.State().ActorStateStoreName() assert.False(t, ok) assert.Empty(t, name) err r.initActors(t.Context()) require.NoError(t, err)这正是 1.6.3 修复所确立的语义没有 actor 状态存储不再是 Actor API 初始化的硬性失败条件。3. 修复方案按角色差异化启用 Actor API发布说明给出的修复结论是This fix changes the actor runtime initialization logic such that, when there is no actor state store available, the API will initialize correctly as long as the service does not register actors. As a result, the Actor API will be available to services acting only as clients (i.e invoking actors) with or without an actor state store component; the Actor API will continue to be unavailable in those services that register actors without providing an actor state store component.拆解为两条明确规则服务角色是否注册 Actor是否配置 actor 状态存储1.6.3 之后的 Actor API 状态纯 Actor 客户端否有✅ 可用可调用其他服务的 Actor纯 Actor 客户端否无✅ 可用本次修复的核心场景Actor 宿主是有✅ 可用Actor 宿主是无❌ 不可用保持既有正确约束修复的本质是把是否具备 actor 状态存储和是否注册 Actor两个条件解耦宿主能力hosting依赖 actor 状态存储缺失时宿主功能不启用调用能力invocation是客户端服务的核心诉求与本地是否配置状态存储无关必须始终可用。在 pkg/actors/actors.go 的Init中可以看到这种降级而非失败的处理方式_, a.hostingName, a.hostingRev, a.hostingActive a.compStore.GetStateStoreActorWithRevision() if !a.hostingActive { log.Info(Actor state store not configured - actor hosting disabled until one is configured, but invocation enabled) } a.table table.New(table.Options{ ReentrancyStore: a.reentrancyStore, StartSuspended: !a.hostingActive, // ... })注意日志措辞actor hosting disabled until one is configured, but invocation enabled宿主被挂起suspended但调用仍然启用这与 1.6.3 的修复语义完全一致并且在此基础上进一步支持了 actor 状态存储的热加载——当后续加载了带actorStateStore标记的状态存储组件时宿主能力会被重新启用见 pkg/actors/actors.go 的convergeHosting逻辑。4. 实战配置用actorStateStore标记 scopes实现角色隔离要正确利用这一修复关键在于状态存储组件上的actorStateStore元数据标记以及组件scopes的作用域隔离。4.1actorStateStore: true标记的解析在 pkg/runtime/processor/state/state.go 中标记的键名被定义为常量PropertyKeyActorStateStore actorstatestore组件初始化时pkg/runtime/processor/state/state.go只有当服务启用了 Actors.actorsEnabled且元数据中存在actorStateStore且值为真时该存储才会被注册为actor 状态存储AddStateStoreActor并通知 Actor 运行时for k, v : range props { if strings.ToLower(k) PropertyKeyActorStateStore { actorStoreSpecified kitstrings.IsTruthy(v) break } } if actorStoreSpecified { if err s.compStore.AddStateStoreActor(comp.Name, store); err ! nil { // 例如detected duplicate actor state store: mystore and otherstore return rterrors.NewInit(rterrors.InitComponentFailure, fName, err) } log.Info(Using comp.Name as actor state store) s.actors.OnActorStateStoreChanged() }底层槽位管理在 pkg/runtime/compstore/statestore.go 的AddStateStoreActor中完成它维护独立的actorStateStore槽位并递增修订号rev同一时刻只允许一个 actor 状态存储若同时注册第二个会返回detected duplicate actor state store错误。对应的行为已被 pkg/runtime/processor/state/state_test.go 中的测试用例覆盖验证。4.2 完整配置示例可复制以下是仓库 e2e 测试中真实使用的 actor 状态存储配置tests/config/dapr_postgres_state_actorstore.yaml可作为宿主服务的参考模板apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore-actors spec: type: state.postgres version: v2 metadata: - name: connectionString value: hostdapr-postgres-postgresql.dapr-tests.svc.cluster.local userpostgres passwordexample port5432 connect_timeout10 databasedapr_test - name: tablePrefix value: v2actor - name: metadataTableName value: dapr_metadata_v2actor - name: actorStateStore value: true scopes: # actortestclient is deliberately omitted to ensure that actor_features_test works without a state store - actor1 - actor2 - actorapp - actorfeatures - actorstate - workflowsapp # ...其余 Actor 宿主应用同样的模式也出现在 CosmosDB 示例 tests/config/dapr_cosmosdb_state_actorstore.yaml 中spec: type: state.azure.cosmosdb version: v1 initTimeout: 1m metadata: - name: masterKey secretKeyRef: name: cosmosdb-secret key: primaryMasterKey - name: url secretKeyRef: name: cosmosdb-secret key: url - name: database value: dapre2e - name: collection value: items - name: actorStateStore value: true两个配置的scopes中都有一句关键注释# actortestclient is deliberately omitted to ensure that actor_features_test works without a state store这正是 1.6.3 修复在真实项目中的落地方式actortestclient纯客户端测试应用被有意排除在该组件的作用域之外从而验证客户端在没有 actor 状态存储时依然可以正常工作这一行为。4.3 两种服务的部署建议Actor 宿主服务为应用配置或通过 Kubernetes 注解注册 Actor 类型的entities并将带actorStateStore: true的状态存储组件通过scopes绑定到该应用。若缺失该组件Actor 宿主能力不可用保持 1.6.3 之前的正确约束。纯 Actor 客户端服务不注册任何 Actor 类型不依赖任何带actorStateStore标记的组件。客户端只需确保 daprd 能解析到目标应用的 placement 信息即可发起调用本地有无状态存储不影响 Actor 调用 API 的可用性。5. 源码验证与测试覆盖1.6.3 修复确立的行为在当前仓库中可从三个层面验证运行时初始化pkg/runtime/runtime.go 中缺少 actor 状态存储时仅记录log.Info不再返回错误Actor 运行时降级pkg/actors/actors.go 以StartSuspended: !a.hostingActive挂起宿主、保留调用能力并在日志中明确输出invocation enabled回归测试pkg/runtime/runtime_test.go 的 the actor store can not be initialized normally 用例直接断言无存储时initActors成功pkg/runtime/processor/state/state_test.go 覆盖了 actor 状态存储的标记、通知、重复注册报错等完整生命周期e2e 层面tests/config/dapr_postgres_state_actorstore.yaml 与 tests/config/dapr_cosmosdb_state_actorstore.yaml 通过scopes排除纯客户端应用持续守护无状态存储的客户端可调用 Actor这一行为。此外后续演进还在此基础上增强了 actor 状态存储的热加载能力actors: allow hot reloading the actor state store相关提交使状态存储在运行时被添加、替换或移除时宿主能力能够动态挂起与恢复pkg/actors/actors.go进一步印证了存储缺失不应导致整个 Actor API 不可用这一设计原则的延续。6. 小结Dapr 1.6.3 的这一项修复虽小却解决了多应用架构中的一个真实痛点让只调 Actor、不存 Actor的客户端服务摆脱对 actor 状态存储的隐性依赖。修复后的行为可以概括为一句话Actor API 对纯客户端始终可用只有注册了 Actor 的宿主服务才强制要求 actor 状态存储。理解并正确运用actorStateStore: true标记与scopes作用域即可在集群中安全地混布宿主与客户端两类服务同时获得发布说明所承诺的行为保证。【免费下载链接】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),仅供参考
返回列表