!clt #13523 Don't expose sender in cluster client replies
This commit is contained in:
parent
e19d3cb3e8
commit
7533df48cf
5 changed files with 41 additions and 25 deletions
|
|
@ -524,7 +524,7 @@ object ClusterReceptionist {
|
|||
def receive = {
|
||||
case Ping ⇒ // keep alive from client
|
||||
case ReceiveTimeout ⇒ context stop self
|
||||
case msg ⇒ client forward msg
|
||||
case msg ⇒ client.tell(msg, Actor.noSender)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -546,10 +546,11 @@ object ClusterReceptionist {
|
|||
*
|
||||
* Response messages from the destination actor are tunneled via the receptionist
|
||||
* to avoid inbound connections from other cluster nodes to the client, i.e.
|
||||
* the `sender`, as seen by the destination actor, is not the client itself.
|
||||
* The `sender` of the response messages, as seen by the client, is preserved
|
||||
* as the original sender, so the client can choose to send subsequent messages
|
||||
* directly to the actor in the cluster.
|
||||
* the `sender()`, as seen by the destination actor, is not the client itself.
|
||||
* The `sender()` of the response messages, as seen by the client, is `deadLetters`
|
||||
* since the client should normally send subsequent messages via the `ClusterClient`.
|
||||
* It is possible to pass the the original sender inside the reply messages if
|
||||
* the client is supposed to communicate directly to the actor in the cluster.
|
||||
*
|
||||
*/
|
||||
final class ClusterReceptionist(pubSubMediator: ActorRef, settings: ClusterReceptionistSettings)
|
||||
|
|
|
|||
|
|
@ -41,11 +41,13 @@ object ClusterClientSpec extends MultiNodeConfig {
|
|||
|
||||
testTransport(on = true)
|
||||
|
||||
case class Reply(msg: Any, node: Address)
|
||||
|
||||
class TestService(testActor: ActorRef) extends Actor {
|
||||
def receive = {
|
||||
case msg ⇒
|
||||
testActor forward msg
|
||||
sender() ! msg + "-ack"
|
||||
sender() ! Reply(msg + "-ack", Cluster(context.system).selfAddress)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +118,7 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod
|
|||
val c = system.actorOf(ClusterClient.props(
|
||||
ClusterClientSettings(system).withInitialContacts(initialContacts)), "client1")
|
||||
c ! ClusterClient.Send("/user/testService", "hello", localAffinity = true)
|
||||
expectMsg("hello-ack")
|
||||
expectMsgType[Reply].msg should be("hello-ack")
|
||||
system.stop(c)
|
||||
}
|
||||
runOn(fourth) {
|
||||
|
|
@ -190,18 +192,18 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod
|
|||
ClusterClientSettings(system).withInitialContacts(initialContacts)), "client2")
|
||||
|
||||
c ! ClusterClient.Send("/user/service2", "bonjour", localAffinity = true)
|
||||
expectMsg("bonjour-ack")
|
||||
val lastSenderAddress = lastSender.path.address
|
||||
val receptionistRoleName = roleName(lastSenderAddress) match {
|
||||
val reply = expectMsgType[Reply]
|
||||
reply.msg should be("bonjour-ack")
|
||||
val receptionistRoleName = roleName(reply.node) match {
|
||||
case Some(r) ⇒ r
|
||||
case None ⇒ fail("unexpected missing roleName: " + lastSender.path.address)
|
||||
case None ⇒ fail("unexpected missing roleName: " + reply.node)
|
||||
}
|
||||
testConductor.exit(receptionistRoleName, 0).await
|
||||
remainingServerRoleNames -= receptionistRoleName
|
||||
within(remaining - 3.seconds) {
|
||||
awaitAssert {
|
||||
c ! ClusterClient.Send("/user/service2", "hi again", localAffinity = true)
|
||||
expectMsg(1 second, "hi again-ack")
|
||||
expectMsgType[Reply](1 second).msg should be("hi again-ack")
|
||||
}
|
||||
}
|
||||
system.stop(c)
|
||||
|
|
@ -220,11 +222,11 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod
|
|||
ClusterClientSettings(system).withInitialContacts(initialContacts)), "client3")
|
||||
|
||||
c ! ClusterClient.Send("/user/service2", "bonjour2", localAffinity = true)
|
||||
expectMsg("bonjour2-ack")
|
||||
val lastSenderAddress = lastSender.path.address
|
||||
val receptionistRoleName = roleName(lastSenderAddress) match {
|
||||
val reply = expectMsgType[Reply]
|
||||
reply.msg should be("bonjour2-ack")
|
||||
val receptionistRoleName = roleName(reply.node) match {
|
||||
case Some(r) ⇒ r
|
||||
case None ⇒ fail("unexpected missing roleName: " + lastSender.path.address)
|
||||
case None ⇒ fail("unexpected missing roleName: " + reply.node)
|
||||
}
|
||||
// shutdown all but the one that the client is connected to
|
||||
remainingServerRoleNames.foreach { r ⇒
|
||||
|
|
@ -244,9 +246,9 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod
|
|||
val expectedAddress = node(receptionistRoleName).address
|
||||
awaitAssert {
|
||||
c ! ClusterClient.Send("/user/service2", "bonjour3", localAffinity = true)
|
||||
expectMsg(1 second, "bonjour3-ack")
|
||||
val lastSenderAddress = lastSender.path.address
|
||||
lastSenderAddress should be(expectedAddress)
|
||||
val reply = expectMsgType[Reply](1 second)
|
||||
reply.msg should be("bonjour3-ack")
|
||||
reply.node should be(expectedAddress)
|
||||
}
|
||||
system.stop(c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,9 +54,10 @@ to the named topic.
|
|||
Response messages from the destination actor are tunneled via the receptionist
|
||||
to avoid inbound connections from other cluster nodes to the client, i.e.
|
||||
the ``sender()``, as seen by the destination actor, is not the client itself.
|
||||
The ``sender()`` of the response messages, as seen by the client, is preserved
|
||||
as the original sender(), so the client can choose to send subsequent messages
|
||||
directly to the actor in the cluster.
|
||||
The ``sender()`` of the response messages, as seen by the client, is ``deadLetters``
|
||||
since the client should normally send subsequent messages via the ``ClusterClient``.
|
||||
It is possible to pass the the original sender inside the reply messages if
|
||||
the client is supposed to communicate directly to the actor in the cluster.
|
||||
|
||||
While establishing a connection to a receptionist the ``ClusterClient`` will buffer
|
||||
messages and send them when the connection is established. If the buffer is full
|
||||
|
|
|
|||
|
|
@ -297,6 +297,17 @@ is now started as a ``system`` actor instead of a ``user`` actor, i.e. the defau
|
|||
the ``ClusterClient`` initial contacts has changed to
|
||||
``"akka.tcp://system@hostname:port/system/receptionist"``.
|
||||
|
||||
ClusterClient sender
|
||||
====================
|
||||
|
||||
In 2.3 the ``sender()`` of the response messages, as seen by the client, was the
|
||||
actor in cluster.
|
||||
|
||||
In 2.4 the ``sender()`` of the response messages, as seen by the client, is ``deadLetters``
|
||||
since the client should normally send subsequent messages via the ``ClusterClient``.
|
||||
It is possible to pass the the original sender inside the reply messages if
|
||||
the client is supposed to communicate directly to the actor in the cluster.
|
||||
|
||||
Akka Persistence
|
||||
================
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,10 @@ to the named topic.
|
|||
Response messages from the destination actor are tunneled via the receptionist
|
||||
to avoid inbound connections from other cluster nodes to the client, i.e.
|
||||
the ``sender()``, as seen by the destination actor, is not the client itself.
|
||||
The ``sender()`` of the response messages, as seen by the client, is preserved
|
||||
as the original sender(), so the client can choose to send subsequent messages
|
||||
directly to the actor in the cluster.
|
||||
The ``sender()`` of the response messages, as seen by the client, is ``deadLetters``
|
||||
since the client should normally send subsequent messages via the ``ClusterClient``.
|
||||
It is possible to pass the the original sender inside the reply messages if
|
||||
the client is supposed to communicate directly to the actor in the cluster.
|
||||
|
||||
While establishing a connection to a receptionist the ``ClusterClient`` will buffer
|
||||
messages and send them when the connection is established. If the buffer is full
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue