Skip to content

Commit 0cbf8d1

Browse files
feat: use bounded shard rebalancing by default (#8445)
1 parent 1e12bac commit 0cbf8d1

4 files changed

Lines changed: 12 additions & 11 deletions

File tree

BREAKING_CHANGES_V1.6.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ of `Behavior`, `Wire`, `API` (combine with `+`).
4040

4141
| Status | PR / Branch | Component | Type | Change | Migration |
4242
|--------|-------------|-----------|------|--------|-----------|
43+
| Planned | `feature/default-bounded-shard-rebalancing` | `Akka.Cluster.Sharding` | Behavior | The default `rebalance-absolute-limit` is now `20`, selecting the bounded shard allocation strategy instead of the legacy threshold-based strategy. | To retain the legacy strategy temporarily, explicitly set `akka.cluster.sharding.least-shard-allocation-strategy.rebalance-absolute-limit = 0`. Review `rebalance-threshold` and `max-simultaneous-rebalance`, which do not apply while the bounded strategy is active. |
4344
| Planned | `fix/artery-daemonmsgcreate-control-stream` | `Akka.Remote` (Artery) | Behavior | Remote deployment's `DaemonMsgCreate` now travels over Artery's CONTROL stream (as a plain envelope, no delivery/ack sequencing) instead of the ordinary stream, ordering it ahead of the `Watch` that remote deployment sends immediately afterwards. Previously the two rode independent, unordered TCP connections and `Watch` systematically arrived first, so the receiver replied `DeathWatchNotification(existenceConfirmed: false)` for a not-yet-created actor and the deployer reaped the freshly-deployed routee before its `Supervise` registration landed, emptying cluster router pools. Additionally (Pekko parity), inbound ordinary messages addressed to a remote-deployed recipient that has not been created yet are no longer dead-lettered immediately: the resolve is retried on a bounded schedule (20 attempts x 50ms, buffered per recipient in FIFO order) so first messages that arrive ahead of the in-flight `DaemonMsgCreate` are delivered once the actor exists; paths that never resolve are banned and dead-letter as before. | No action required -- this is a bug fix restoring correct create-before-watch ordering; code that (incorrectly) depended on the old race is unsupported. |
4445
| Planned | `feature/artery-test-mode` | `Akka.Remote` | Behavior | System UID generation (`AddressUidExtension` / `AddressUid`) now uses a cryptographic RNG instead of the `Environment.TickCount`-seeded `ThreadLocalRandom`. Previously, multiple processes started within the same millisecond tick (e.g. every node of a multi-node test spawning at once) could draw IDENTICAL system UIDs, silently corrupting Artery's uid-keyed identity (handshakes, quarantine, association reverse index). UIDs remain nonzero and in the legacy `[1, int.MaxValue]` range at the default (`use-64bit-system-uids = off`). | Nothing required -- UIDs were always documented as random; only code depending on the (buggy) time-seeded determinism could observe a difference. |
4546
| Planned | `feature/artery-test-mode` | `Akka.Remote` (Artery) / `Akka.Remote.TestKit` | Behavior | New `akka.remote.artery.advanced.test-mode` setting (default `off`, Pekko key parity) enables failure-injection test stages in Artery's stream pipelines, and `ArteryRemoting.ManagementCommand` now honors `SetThrottle` with `Blackhole`/`Unthrottled` (returning `true`; previously always `false`) so TestConductor `Blackhole`/`PassThrough` work over Artery. Rate throttles (`TokenBucket`) and `ForceDisassociate` remain unsupported on Artery (still `false`, matching Pekko). `MultiNodeConfig.TestTransport = true` now also sets Artery test-mode on, and the TestKit `Player` now treats a `false` `ManagementCommand` result as a failure (previously reported success for a silently ignored command). | Nothing at the default (`test-mode = off` composes byte-identical pipelines). Test code that relied on `ManagementCommand` always returning `false` on Artery, or on the Player treating `false` as success, must account for the new semantics. |

src/contrib/cluster/Akka.Cluster.Sharding.Tests/ClusterShardingConfigSpec.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public static Config GetConfig()
2828
[Fact]
2929
public void Should_cluster_sharding_settings_have_default_config()
3030
{
31-
ClusterSharding.Get(Sys);
31+
var clusterSharding = ClusterSharding.Get(Sys);
3232
var config = Sys.Settings.Config.GetConfig("akka.cluster.sharding");
3333

3434
var clusterShardingSettings = ClusterShardingSettings.Create(Sys);
@@ -55,6 +55,10 @@ public void Should_cluster_sharding_settings_have_default_config()
5555

5656
Assert.Equal(1, config.GetInt("least-shard-allocation-strategy.rebalance-threshold"));
5757
Assert.Equal(3, config.GetInt("least-shard-allocation-strategy.max-simultaneous-rebalance"));
58+
Assert.Equal(20, config.GetInt("least-shard-allocation-strategy.rebalance-absolute-limit"));
59+
Assert.Equal(0.1, config.GetDouble("least-shard-allocation-strategy.rebalance-relative-limit"));
60+
clusterSharding.DefaultShardAllocationStrategy(clusterShardingSettings)
61+
.Should().BeOfType<Sharding.Internal.LeastShardAllocationStrategy>();
5862

5963
Assert.Equal("all", config.GetString("entity-recovery-strategy"));
6064
Assert.Equal(TimeSpan.FromMilliseconds(100), config.GetTimeSpan("entity-recovery-constant-rate-strategy.frequency"));

src/contrib/cluster/Akka.Cluster.Sharding/ClusterSharding.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,8 +1475,7 @@ public IShardAllocationStrategy DefaultShardAllocationStrategy(ClusterShardingSe
14751475
}
14761476
else
14771477
{
1478-
// TODO: remove this in v1.6 and force all users to use only the new strategy going forward
1479-
// old algorithm
1478+
// Explicit compatibility mode for deployments that still use the legacy strategy.
14801479
var threshold = settings.TuningParameters.LeastShardAllocationRebalanceThreshold;
14811480
var maxSimultaneousRebalance = settings.TuningParameters.LeastShardAllocationMaxSimultaneousRebalance;
14821481
#pragma warning disable CS0618 // Type or member is obsolete

src/contrib/cluster/Akka.Cluster.Sharding/reference.conf

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,14 @@ akka.cluster.sharding {
100100

101101
# Settings for LeastShardAllocationStrategy.
102102
#
103-
# A new rebalance algorithm was included in Akka.Net 1.4.11. It can reach optimal balance in
104-
# less rebalance rounds (typically 1 or 2 rounds). The amount of shards to rebalance in each
105-
# round can still be limited to make it progress slower. For backwards compatibility
106-
# the new algorithm is not enabled by default. Enable the new algorithm by setting
107-
# `rebalance-absolute-limit` > 0, for example:
108-
# akka.cluster.sharding.least-shard-allocation-strategy.rebalance-absolute-limit=20
109-
# The new algorithm is recommended and will become the default in future versions of Akka.
103+
# The bounded rebalance algorithm can reach optimal balance in fewer rebalance rounds than the
104+
# legacy threshold-based algorithm. The absolute and relative limits bound the number of shards
105+
# moved in each round. Set `rebalance-absolute-limit = 0` only to retain legacy behavior during
106+
# migration.
110107
least-shard-allocation-strategy {
111108
# Maximum number of shards that will be rebalanced in one rebalance round.
112109
# The lower of this and `rebalance-relative-limit` will be used.
113-
rebalance-absolute-limit = 0
110+
rebalance-absolute-limit = 20
114111

115112
# Maximum number of shards that will be rebalanced in one rebalance round.
116113
# Fraction of total number of (known) shards.

0 commit comments

Comments
 (0)