=act, rem #2556 Optimize subscriptions of AddressTerminated

* unsubscribe in eventStream is too slow when using many actors
  that are watching remote actors, and becomes a problem for example
  when shutting down such a system
* Previous eventStream solution:
  Stopping 20000 actors took 50355 ms
* This solution:
  Stopping 20000 actors took 764 ms
This commit is contained in:
Patrik Nordwall 2014-03-07 13:20:57 +01:00
parent ac5f4fc72e
commit 67925cb94e
7 changed files with 126 additions and 12 deletions

View file

@ -20,6 +20,7 @@ import akka.actor.SelectChildPattern
import akka.actor.Identify
import akka.actor.ActorIdentity
import akka.actor.EmptyLocalActorRef
import akka.event.AddressTerminatedTopic
/**
* INTERNAL API
@ -52,7 +53,7 @@ private[akka] class RemoteSystemDaemon(
private val terminating = new Switch(false)
system.eventStream.subscribe(this, classOf[AddressTerminated])
AddressTerminatedTopic(system).subscribe(this)
/**
* Find the longest matching path which we know about and return that ref

View file

@ -19,6 +19,7 @@ import akka.actor.InternalActorRef
import akka.dispatch.sysmsg.DeathWatchNotification
import akka.dispatch.sysmsg.Watch
import akka.actor.Deploy
import akka.event.AddressTerminatedTopic
/**
* INTERNAL API
@ -79,7 +80,7 @@ private[akka] object RemoteWatcher {
* to the peer actor on the other node, which replies with [[RemoteWatcher.HeartbeatRsp]]
* message back. The failure detector on the watching side monitors these heartbeat messages.
* If arrival of hearbeat messages stops it will be detected and this actor will publish
* [[akka.actor.AddressTerminated]] to the `eventStream`.
* [[akka.actor.AddressTerminated]] to the [[akka.event.AddressTerminatedTopic]].
*
* When all actors on a node have been unwatched it will stop sending heartbeat messages.
*
@ -171,7 +172,7 @@ private[akka] class RemoteWatcher(
}
def publishAddressTerminated(address: Address): Unit =
context.system.eventStream.publish(AddressTerminated(address))
AddressTerminatedTopic(context.system).publish(AddressTerminated(address))
def quarantine(address: Address, uid: Option[Int]): Unit =
remoteProvider.quarantine(address, uid)

View file

@ -22,6 +22,7 @@ import scala.util.{ Failure, Success }
import akka.remote.transport.AkkaPduCodec.Message
import java.util.concurrent.ConcurrentHashMap
import akka.dispatch.{ RequiresMessageQueue, UnboundedMessageQueueSemantics }
import akka.event.AddressTerminatedTopic
/**
* INTERNAL API
@ -398,7 +399,7 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
"Address is now gated for {} ms, all messages to this address will be delivered to dead letters. Reason: {}",
remoteAddress, settings.RetryGateClosedFor.toMillis, reason.getMessage)
endpoints.markAsFailed(sender(), Deadline.now + settings.RetryGateClosedFor)
context.system.eventStream.publish(AddressTerminated(remoteAddress))
AddressTerminatedTopic(context.system).publish(AddressTerminated(remoteAddress))
Stop
case ShutDownAssociation(localAddress, remoteAddress, _)
@ -406,7 +407,7 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
"Address is now gated for {} ms, all messages to this address will be delivered to dead letters.",
remoteAddress, settings.RetryGateClosedFor.toMillis)
endpoints.markAsFailed(sender(), Deadline.now + settings.RetryGateClosedFor)
context.system.eventStream.publish(AddressTerminated(remoteAddress))
AddressTerminatedTopic(context.system).publish(AddressTerminated(remoteAddress))
Stop
case HopelessAssociation(localAddress, remoteAddress, Some(uid), _)
@ -416,7 +417,7 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
eventPublisher.notifyListeners(QuarantinedEvent(remoteAddress, uid))
case _ // disabled
}
context.system.eventStream.publish(AddressTerminated(remoteAddress))
AddressTerminatedTopic(context.system).publish(AddressTerminated(remoteAddress))
Stop
case HopelessAssociation(localAddress, remoteAddress, None, _)
@ -424,7 +425,7 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
"Address cannot be quarantined without knowing the UID, gating instead for {} ms.",
remoteAddress, settings.RetryGateClosedFor.toMillis)
endpoints.markAsFailed(sender(), Deadline.now + settings.RetryGateClosedFor)
context.system.eventStream.publish(AddressTerminated(remoteAddress))
AddressTerminatedTopic(context.system).publish(AddressTerminated(remoteAddress))
Stop
case NonFatal(e)