Merge pull request #25595 from akka/wip-25336-orset-actorref-patriknw

Revert Support for rolling upgrade of ORSet[ActorRef], #25336
This commit is contained in:
Patrik Nordwall 2018-09-26 14:21:00 +02:00 committed by GitHub
commit 6464dea52b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 95 additions and 61 deletions

View file

@ -1,4 +1,10 @@
# #25543 allow BigInt increment and decrements in PNCounter
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.cluster.ddata.PNCounter.increment")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.cluster.ddata.PNCounter.decrement")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.cluster.ddata.PNCounter.change")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.cluster.ddata.PNCounter.change")
# #25336 Revert Support for rolling upgrade of ORSet[ActorRef]
ProblemFilters.exclude[MissingClassProblem]("akka.cluster.ddata.protobuf.ReplicatedDataSerializer$BothOldAndNewActorRefFormat$")
ProblemFilters.exclude[MissingClassProblem]("akka.cluster.ddata.protobuf.ReplicatedDataSerializer$NewActorRefFormat$")
ProblemFilters.exclude[MissingClassProblem]("akka.cluster.ddata.protobuf.ReplicatedDataSerializer$OldActorRefFormat$")
ProblemFilters.exclude[MissingClassProblem]("akka.cluster.ddata.protobuf.ReplicatedDataSerializer$ActorRefFormat")

View file

@ -28,7 +28,6 @@ import java.io.NotSerializableException
import akka.actor.ActorRef
import akka.cluster.ddata.protobuf.msg.ReplicatorMessages.OtherMessage
import akka.serialization.Serialization
import akka.util.Helpers.toRootLowerCase
private object ReplicatedDataSerializer {
/*
@ -168,16 +167,6 @@ private object ReplicatedDataSerializer {
override def getValue(entry: rd.ORMapDeltaGroup.MapEntry): dm.OtherMessage = entry.getValue
}
// Optimized serializer for ORSet[ActorRef] was added in 2.5.14.
// To support rolling upgrades from Akka 2.5.13 to 2.5.14 and then to 2.5.15 those elements
// are by default sent as both old and new elements in 2.5.14.
// The old is used by 2.5.13 receivers. The new is used by 2.5.14 and 2.5.15 receivers.
// FIXME Remove this in 2.5.15
private sealed trait ActorRefFormat
private case object OldActorRefFormat extends ActorRefFormat
private case object BothOldAndNewActorRefFormat extends ActorRefFormat
private case object NewActorRefFormat extends ActorRefFormat
}
/**
@ -188,20 +177,6 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
import ReplicatedDataSerializer._
private val actorRefFormat: ActorRefFormat = {
val conf = system.settings.config
val confKey = "akka.cluster.distributed-data.actor-ref-format"
// this config is not in reference.conf because it's only temporary for the 2.5.14 release
if (conf.hasPath(confKey)) {
toRootLowerCase(conf.getString(confKey)) match {
case "old" OldActorRefFormat
case "both" BothOldAndNewActorRefFormat
case "new" NewActorRefFormat
}
} else
BothOldAndNewActorRefFormat
}
private val DeletedDataManifest = "A"
private val GSetManifest = "B"
private val GSetKeyManifest = "b"
@ -350,20 +325,11 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
val otherElements = new ArrayList[dm.OtherMessage]
val actorRefElements = new ArrayList[String]
gset.elements.foreach {
case s: String stringElements.add(s)
case i: Int intElements.add(i)
case l: Long longElements.add(l)
case ref: ActorRef
actorRefFormat match {
case BothOldAndNewActorRefFormat
actorRefElements.add(Serialization.serializedActorPath(ref))
otherElements.add(otherMessageToProto(ref))
case OldActorRefFormat
otherElements.add(otherMessageToProto(ref))
case NewActorRefFormat
actorRefElements.add(Serialization.serializedActorPath(ref))
}
case other otherElements.add(otherMessageToProto(other))
case s: String stringElements.add(s)
case i: Int intElements.add(i)
case l: Long longElements.add(l)
case ref: ActorRef actorRefElements.add(Serialization.serializedActorPath(ref))
case other otherElements.add(otherMessageToProto(other))
}
if (!stringElements.isEmpty) {
Collections.sort(stringElements)
@ -415,26 +381,10 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
var otherElementsMap = Map.empty[dm.OtherMessage, Any]
val actorRefElements = new ArrayList[ActorRef]
orset.elementsMap.keysIterator.foreach {
case s: String stringElements.add(s)
case i: Int intElements.add(i)
case l: Long longElements.add(l)
case ref: ActorRef
actorRefFormat match {
case BothOldAndNewActorRefFormat
actorRefElements.add(ref)
val enclosedMsg = otherMessageToProto(ref)
otherElements.add(enclosedMsg)
// need the mapping back to the `other` when adding dots
otherElementsMap = otherElementsMap.updated(enclosedMsg, ref)
case OldActorRefFormat
otherElements.add(otherMessageToProto(ref))
val enclosedMsg = otherMessageToProto(ref)
otherElements.add(enclosedMsg)
// need the mapping back to the `other` when adding dots
otherElementsMap = otherElementsMap.updated(enclosedMsg, ref)
case NewActorRefFormat
actorRefElements.add(ref)
}
case s: String stringElements.add(s)
case i: Int intElements.add(i)
case l: Long longElements.add(l)
case ref: ActorRef actorRefElements.add(ref)
case other
val enclosedMsg = otherMessageToProto(other)
otherElements.add(enclosedMsg)

View file

@ -5,8 +5,9 @@
@@@ index
* [migration-guides](migration-guides.md)
* [rolling-update](rolling-update.md)
* [issue-tracking](issue-tracking.md)
* [licenses](licenses.md)
* [links](links.md)
@@@
@@@

View file

@ -425,6 +425,8 @@ and here is a summary of things to consider.
* [akka.cluster.sharding.state-store-mode](#mig25-sharding-store)
* [akka.remote.netty.ssl.require-mutual-authentication](#mig25-mutual)
See also the @ref:[rolling update guide](rolling-update.md) for specifics about later patch releases.
#### Limit lookup of routees to nodes tagged with multiple roles
Starting with 2.5.4, cluster routing supports delivering messages to routees tagged with all specified roles

View file

@ -0,0 +1,75 @@
# Rolling Updates
## Introduction
A rolling update is the process of replacing one version of the system with another without downtime.
The changes can be new code, changed dependencies such as new Akka version, or modified configuration.
Rolling updates are typically used for a stateful Akka Cluster where you can't run two separate clusters in
parallel during the update as in blue green deployments.
There are two parts of Akka that need careful consideration when performing an rolling update.
1. Compatibility of remote message protocols. Old nodes may send messages to new nodes and vice versa.
1. Serialization format of persisted events and snapshots. New nodes must be able to read old data, and
during the update old nodes must be able to read data stored by new nodes.
There are many more application specific aspects. It's important to have a strategy for serialization
format that can be evolved and you can find advice in
@ref:[Persistence - Schema Evolution](../persistence-schema-evolution.md), which also applies to
remote messages when deploying with rolling updates.
Akka supports rolling updates between two consecutive patch versions unless an exception is
mentioned on this page. For example updating Akka version from 2.5.15 to 2.5.16. Many times
it is also possible to skip several versions and exceptions to that are also described here.
For example it's possible to update from 2.5.14 to 2.5.16 without intermediate 2.5.15.
It's not supported to have a cluster with more than two different versions. Roll out the first
update completely before starting next update.
## Shutdown order
It's best to keep the node that has been running the longest until last. That is because
Cluster Singletons (including Cluster Sharding coordinators) are running on the oldest nodes. It's more
efficient to avoid moving the singletons more than necessary since those typically have to recover
their state and it might introduce unnecessary delays in for example access to new sharded actors.
## Change log
### 2.5.0 Several changes in minor release
See @ref:[migration guide](migration-guide-2.4.x-2.5.x.md#rolling-update) when updating from 2.4.x to 2.5.x.
### 2.5.10 Joining regression
Issue: [#24622](https://github.com/akka/akka/issues/24622)
Incompatible change was introduced in 2.5.10 and fixed in 2.5.11.
This means that you can't do a rolling update from 2.5.9 to 2.5.10 and must instead do update from 2.5.9 to 2.5.11.
### 2.5.10 Joining old versions
Issue: [#25491](https://github.com/akka/akka/issues/25491)
Incompatibility was introduced in in 2.5.10 and fixed in 2.5.15.
That means that you should do rolling update from 2.5.9 directly to 2.5.15 if you need to be able to
join 2.5.9 nodes during the update phase.
### 2.5.14 Distributed Data serializer for `ORSet[ActorRef]`
Issue: [#23703](https://github.com/akka/akka/issues/23703)
Intentional change was done in 2.5.14.
This change required a two phase update where the data was duplicated to be compatible with both old and new nodes.
* 2.5.13 - old format, before the change. Can communicate with intermediate format and with old format.
* 2.5.14, 2.5.15, 2.5.16 - intermediate format. Can communicate with old format and with new format.
* 2.5.17 - new format. Can communicate with intermediate format and with new format.
This means that you can't update from 2.5.13 directly to 2.5.17. You must first update to one of the intermediate
versions 2.5.14, 2.5.15, or 2.5.16.