=rem improve remote watching mechanism

This improves the remote watching mechanism as follows: Watch requests
are intercepted by the RemoteWatcher and not sent on the wire,
excepted watches from the remoteWatcher itself.

RemoteWatcher is then in charge of forwarding DeathWatchNotification
messages to the watchers.

This reduces the number of watch message to one per watchee, even if
there are several watcher on the same watchee (instead of n+1 before).

Reversed watch messages, and watch on ref with undefinedUid are excluded from
interception by the RemoteWatcher and so are handled as before this commit.

In addition, the following changes are made:
- Keep watchers in a map watchee -> watchers for more efficient retrieval
(in a scala Multimap)
- Keep watchees in a map address -> watchee for more efficient retrieval
(in a scala Multimap)
- Use of InternalActorRef more thoroughly to avoid casts
- Rewatch use a standard watch message, as the distinction is longer needed
This commit is contained in:
Thibaut Robert 2015-02-19 15:49:02 +01:00
parent 493666999c
commit 12cbf83927
7 changed files with 173 additions and 202 deletions

View file

@ -4,16 +4,13 @@
package akka.cluster
import scala.concurrent.duration.FiniteDuration
import akka.actor.Actor
import akka.actor.Address
import akka.actor.Props
import akka.actor._
import akka.cluster.ClusterEvent.CurrentClusterState
import akka.cluster.ClusterEvent.MemberEvent
import akka.cluster.ClusterEvent.MemberUp
import akka.cluster.ClusterEvent.MemberRemoved
import akka.remote.FailureDetectorRegistry
import akka.remote.RemoteWatcher
import akka.actor.Deploy
/**
* INTERNAL API
@ -36,7 +33,7 @@ private[cluster] object ClusterRemoteWatcher {
*
* Specialization of [[akka.remote.RemoteWatcher]] that keeps
* track of cluster member nodes and is responsible for watchees on cluster nodes.
* [[akka.actor.AddressTerminate]] is published when node is removed from cluster.
* [[akka.actor.AddressTerminated]] is published when node is removed from cluster.
*
* `RemoteWatcher` handles non-cluster nodes. `ClusterRemoteWatcher` will take
* over responsibility from `RemoteWatcher` if a watch is added before a node is member
@ -53,8 +50,6 @@ private[cluster] class ClusterRemoteWatcher(
unreachableReaperInterval,
heartbeatExpectedResponseAfter) {
import RemoteWatcher._
val cluster = Cluster(context.system)
import cluster.selfAddress
@ -73,8 +68,6 @@ private[cluster] class ClusterRemoteWatcher(
override def receive = receiveClusterEvent orElse super.receive
def receiveClusterEvent: Actor.Receive = {
case WatchRemote(watchee, watcher) if clusterNodes(watchee.path.address)
() // cluster managed node, don't propagate to super
case state: CurrentClusterState
clusterNodes = state.members.collect { case m if m.address != selfAddress m.address }
clusterNodes foreach takeOverResponsibility
@ -96,16 +89,18 @@ private[cluster] class ClusterRemoteWatcher(
case _: MemberEvent // not interesting
}
override def watchNode(watchee: InternalActorRef) =
if (!clusterNodes(watchee.path.address)) super.watchNode(watchee)
/**
* When a cluster node is added this class takes over the
* responsibility for watchees on that node already handled
* by super RemoteWatcher.
*/
def takeOverResponsibility(address: Address): Unit = {
watching foreach {
case (watchee, watcher) if (watchee.path.address == address)
unwatchRemote(watchee, watcher)
def takeOverResponsibility(address: Address): Unit =
if (watchingNodes(address)) {
log.debug("Cluster is taking over responsibility of node: [{}]", address)
unwatchNode(address)
}
}
}