发布日期: 2026-03-09
版本号: v1.17.1

Dapr 1.17.1 更新修复了四个主要缺陷:修复了因文件命名约定导致 WASM 绑定与中间件组件在非 WASM 架构(如 amd64/arm64/arm)上无法注册的问题;解决了已解除停滞的工作流实例无法被状态保留策略或清除 API 删除的问题;优化了当无 Actor 类型的 daprd sidecar 连接或断开 Placement 服务时,不再触发不必要的全集群位置表广播循环,从而降低了服务开销;并修正了批量订阅中,因达到 maxMessagesCount 而提前分发消息后,awaitDuration 计时器未重置,导致后续可能触发不完整批次的问题。

更新内容 (中文)

Dapr 1.17.1

本次更新包含错误修复:

WASM绑定与中间件组件在非WASM架构上注册失败

问题描述

升级至Dapr v1.16.0或更高版本后,使用WASM输出绑定或WASM HTTP中间件组件的应用程序启动失败,错误信息如下:

FATA[0000] Fatal error from runtime: process component wasm error:
[INIT_COMPONENT_FAILURE]: initialization error occurred for wasm
(bindings.wasm/v1): couldn't find binding wasm (bindings.wasm/v1)

影响范围

WASM绑定与WASM HTTP中间件组件在所有生产架构(amd64、arm64、arm)上完全不可用,影响范围涵盖v1.16.0至v1.17.0的所有版本。

根本原因

在v1.16.0版本中,PR #9009为统一命名规范重命名了组件注册文件:

  • binding_webassembly.gobindings_wasm.go
  • middleware_http_webassembly.gomiddleware_http_wasm.go

Go语言在文件名匹配*_GOARCH.go模式时会自动应用隐式构建约束。由于wasm是有效的GOARCH值,后缀为_wasm.go的文件仅在GOARCH=wasm时被编译,导致WASM组件在amd64/arm64/arm平台始终无法注册。此变更意外撤销了#5486和#6439中针对此文件名冲突的修复。

解决方案

将文件重命名回使用_webassembly后缀(该后缀不匹配任何有效的GOARCH值):

  • bindings_wasm.gobindings_webassembly.go
  • middleware_http_wasm.gomiddleware_http_webassembly.go

停滞的工作流无法被状态保留策略删除

问题描述

当停滞的工作流恢复运行(例如重新注册原始工作流版本)后,已完成的工作流实例无法通过状态保留策略或清除API删除。

影响范围

先前停滞后恢复运行的工作流实例将永久保留在状态存储中,即使配置了状态保留策略来清理已完成的工作流。

根本原因

工作流运行时元数据状态跟踪器在工作流恢复运行后未移除内部的Stalled跟踪器。这导致即使工作流处于COMPLETED状态,清除API调用也无法完成。

解决方案

工作流运行时元数据状态跟踪器现在在工作流恢复运行时会移除内部的Stalled跟踪器,允许API调用成功完成,并使状态保留策略能按预期清理已完成的工作流。

无Actor类型的Daprd主机发生不必要的定位信息扩散

问题描述

当无Actor类型的Daprd sidecar连接或断开定位服务时,会触发全量定位表信息扩散至所有已连接的sidecar。在包含大量不托管Actor的sidecar集群中,这会导致不必要的扩散周期,降低定位服务性能。

影响范围

每次Daprd连接和断开操作——即使来自不托管Actor的sidecar——都会触发完整的三阶段锁定扩散周期(LOCK → UPDATE → UNLOCK)至所有已连接sidecar。在大型集群中,许多不托管Actor的sidecar会导致定位服务承受显著开销,并在每个周期内不必要地锁定所有sidecar的Actor调用。

根本原因

定位服务将所有已连接主机存储在扩散表中,无论其是否报告任何Actor类型(实体)。连接和断开这些主机会触发集群范围的扩散周期来传播变更,即使该主机对Actor路由毫无意义。

解决方案

定位服务不再在扩散表中存储无Actor类型的主机,它们的连接或断开操作也不会触发集群范围的扩散。当无类型主机连接时,定位服务通过单次LOCK/UPDATE/UNLOCK序列直接向该单一流发送当前定位表,无需涉及其他已连接sidecar。这确保了无Actor类型的sidecar仍能接收用于路由Actor调用的定位表,同时避免了破坏性的集群范围锁定周期。

因达到maxMessagesCount而提前分发后,批量订阅定时器未重置

问题描述

使用同时配置了maxMessagesCountawaitDuration的批量订阅时,当批次因达到maxMessagesCount而提前分发后,Dapr继续遵循原始定时器。即使下一批次尚未积累足够消息,订阅端点仍会在初始awaitDuration时间到达时再次触发。这导致部分填充批次的不必要触发。

影响范围

使用配置了maxMessagesCountawaitDuration的批量订阅的应用程序,可能在完整批次分发后立即接收到额外的部分填充批次。这会造成不必要的处理开销,并可能导致期望在整个awaitDuration窗口内积累消息的订阅者出现意外行为。

根本原因

processBulkMessagespkg/runtime/pubsub/default_bulksub.go)中的基于计数的刷新操作后,awaitDuration计时器未被重置。计时器从原始启动时间继续计时,导致下一个刻度比预期更早触发——可能立即触发——而非从提前分发时开始等待完整的awaitDuration时间。

解决方案

processBulkMessages中,基于计数的刷新后添加了ticker.Reset(),确保awaitDuration计时器在每次提前分发后从零开始重新计时。现在下一批次将获得完整的时间窗口来积累消息,然后再进行分发。

更新内容 (原始)

Dapr 1.17.1

This update includes bug fixes:

WASM binding and middleware components fail to register on non-wasm architectures

Problem

After upgrading to Dapr v1.16.0 or later, applications using the WASM output binding or WASM HTTP middleware component fail to start with the error:

FATA[0000] Fatal error from runtime: process component wasm error:
[INIT_COMPONENT_FAILURE]: initialization error occurred for wasm
(bindings.wasm/v1): couldn't find binding wasm (bindings.wasm/v1)

Impact

WASM binding and WASM HTTP middleware components are completely unavailable on all production architectures (amd64, arm64, arm), affecting all versions from v1.16.0 through v1.17.0.

Root Cause

In v1.16.0, PR #9009 renamed component registration files for naming consistency:

  • binding_webassembly.gobindings_wasm.go
  • middleware_http_webassembly.gomiddleware_http_wasm.go

Go applies an implicit build constraint when a filename matches *_GOARCH.go. Since wasm is a valid GOARCH value, files ending in _wasm.go are only compiled when GOARCH=wasm, causing the WASM components to never be registered on amd64/arm64/arm platforms. This inadvertently reverted fixes from #5486 and #6439 which specifically addressed this exact filename clash.

Solution

Renamed the files back to use the _webassembly suffix which does not match any valid GOARCH value:

  • bindings_wasm.gobindings_webassembly.go
  • middleware_http_wasm.gomiddleware_http_webassembly.go

Unstalled workflows cannot be deleted by state retention policy

Problem

When a stalled workflow became unstalled (e.g. by re-registering the original workflow version), the completed workflow instance could not be deleted by the state retention policy or the purge API.

Impact

Workflow instances that were previously stalled and then unstalled would remain in the state store indefinitely, even when a state retention policy was configured to clean up completed workflows.

Root Cause

The workflow runtime metadata state tracker did not remove an internal Stalled tracker once a workflow became unstalled. This prevented purge API calls from completing, even when the workflow was in a COMPLETED state.

Solution

The workflow runtime metadata state tracker now removes the internal Stalled tracker when a workflow becomes unstalled, allowing API calls to complete successfully and enabling the state retention policy to clean up completed workflows as expected.

Unnecessary placement dissemination for daprd hosts with no actor types

Problem

When a daprd sidecar with no actor types connected to or disconnected from the placement service, it triggered a full placement table dissemination across all connected sidecars. In clusters with many sidecars that do not host actors, this caused unnecessary dissemination cycles that degraded placement performance.

Impact

Every daprd connection and disconnection—even from sidecars with no actor types—triggered a full 3-stage lock dissemination cycle (LOCK → UPDATE → UNLOCK) across all connected sidecars. In large clusters where many sidecars do not host actors, this created significant overhead on the placement service and caused unnecessary locking of actor invocations on all sidecars during each cycle.

Root Cause

The placement service stored all connected hosts in its dissemination table regardless of whether they reported any actor types (entities). Both connecting and disconnecting these hosts triggered a cluster-wide dissemination cycle to propagate the change, even though the host was never meaningful to actor routing.

Solution

The placement service no longer stores hosts with no actor types in the dissemination table, and neither their connection nor disconnection triggers a cluster-wide dissemination. Instead, when a no-types host connects, the placement service sends the current placement table directly to that single stream via a one-shot LOCK/UPDATE/UNLOCK sequence, without involving any other connected sidecars. This ensures that sidecars without actor types still receive the placement table for routing actor invocations, while avoiding the destructive cluster-wide lock cycle.

Bulk subscription timer not reset after early dispatch due to maxMessagesCount

Problem

When using bulk subscriptions with both maxMessagesCount and awaitDuration configured, after a batch was dispatched early because maxMessagesCount was reached, Dapr continued to honor the original timer. The subscriber endpoint was triggered again when the initial awaitDuration elapsed, even if the next batch had not yet accumulated enough messages. This resulted in unnecessary batch triggers with partially filled batches.

Impact

Applications using bulk subscriptions with maxMessagesCount and awaitDuration could receive additional, partially filled batches immediately after a full batch was dispatched. This caused unnecessary processing overhead and potentially unexpected behavior for subscribers expecting to accumulate messages for the full awaitDuration window.

Root Cause

After a count-based flush in processBulkMessages (pkg/runtime/pubsub/default_bulksub.go), the awaitDuration ticker was not reset. The ticker continued from its original start time, so the next tick fired sooner than expected—potentially immediately—rather than waiting the full awaitDuration from the time of the early dispatch.

Solution

Added ticker.Reset() in processBulkMessages after a count-based flush, ensuring the awaitDuration ticker restarts from zero after each early dispatch. The next batch now gets the full duration window to accumulate messages before being dispatched.

下载链接