AkkaRemote

Akka远程

Akka remoting是按照端到端(peer-to-peer)对等通信的方式设计的

远程交互的类型

Akka 远程调用有两种方式:

  • 查找 : 使用actorSelection(path)在远程主机上查找一个actor
  • 创建 : 使用actorOf(Props(…), actorName)在远程主机上创建一个actor

查找远程 Actors

actorSelection(path)会获得远程结点上一个Actor的ActorSelection, 例如:

1
2
3
4
5
6
7
8
val selection =
context.actorSelection("akka.tcp://actorSystemName@10.0.0.1:2552/user/actorName")
可以看到以下模式被用来在远程结点上查找一个actor:

akka.<protocol>://<actor system>@<hostname>:<port>/<actor path>
一旦得到了actor的selection,你就可以像与本地actor通讯一样与它进行通迅, 例如:

selection ! "Pretty awesome feature"

用代码进行远程部署

要允许动态部署系统,也可以在用来创建actor的Props中包含deployment配置 : 这一部分信息与配置文件中的deployment部分是等价的, 如果两者都有,则外部配置拥有更高的优先级.

1
2
3
4
5
6
7
8
9
10
11
12
加入这些import:

import akka.actor.{ Props, Deploy, Address, AddressFromURIString }
import akka.remote.RemoteScope
和一个像这样的远程地址:

val one = AddressFromURIString("akka.tcp://sys@host:1234")
val two = Address("akka.tcp", "sys", "host", 1234) // this gives the same
你可以像这样建议系统在此远程结点上创建一个子actor:

val ref = system.actorOf(Props[SampleActor].
withDeploy(Deploy(scope = RemoteScope(address))))

序列化

对actor使用远程调用时,你必须保证这些actor所使用的props和messages是可序列化的. 如果不能保证会导致系统产生意料之外的行为.
配置

  1. 为了让 Akka 知道对什么任务使用哪个Serializer, 你需要编辑你的 配置文件, 在 “akka.actor.serializers”一节将名称绑定为akka.serialization.Serializer的实现

  2. 在将名称与Serializer的不同实现绑定后,你需要指定哪些类的序列化使用哪种Serializer, 这部分配置写在“akka.actor.serialization-bindings”一节中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    akka {
    actor {
    serializers {
    java = "akka.serialization.JavaSerializer"
    proto = "akka.remote.serialization.ProtobufSerializer"
    myown = "docs.serialization.MyOwnSerializer"
    }

    serialization-bindings {
    "java.lang.String" = java
    "docs.serialization.Customer" = java
    "com.google.protobuf.Message" = proto
    "docs.serialization.MyOwnSerializable" = myown
    "java.lang.Boolean" = myown
    }
    }
    }

自定义 创建新的 Serializer

首先你需要为你的 Serializer 写一个类定义,像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import akka.actor.{ ActorRef, ActorSystem }
import akka.serialization._
import com.typesafe.config.ConfigFactory

class MyOwnSerializer extends Serializer {

// This is whether "fromBinary" requires a "clazz" or not
def includeManifest: Boolean = false

// Pick a unique identifier for your Serializer,
// you've got a couple of billions to choose from,
// 0 - 16 is reserved by Akka itself
def identifier = 1234567

// "toBinary" serializes the given object to an Array of Bytes
def toBinary(obj: AnyRef): Array[Byte] = {
// Put the code that serializes the object here
// ... ...
}

// "fromBinary" deserializes the given array,
// using the type hint (if any, see "includeManifest" above)
// into the optionally provided classLoader.
def fromBinary(bytes: Array[Byte],
clazz: Option[Class[_]]): AnyRef = {
// Put your code that deserializes here
// ... ...
}
}

远程事件

可以监听Akka远程调用中发生的事件,也可以订阅/取消订阅这些事情,你只需要在ActorSystem.eventStream中为下面所列出类型的事件注册监听器.

注意
若要订阅任意远程事件,订阅RemotingLifecycleEvent。若要订阅只涉及链接的生命周期的事件,请订阅akka.remote.AssociationEvent。

注意
使用”链接”而不是”连接”一词,反映了远程处理子系统可能使用无连接传输,但链接类似于运输层连接,来维持点到点之间的Akka协议。

远程安全

Akka提供了几种方式来加强远程节点(客户端/服务器)之间的安全:

  • 不受信任的模式
  • 安全 Cookie 握手
  1. 配置为不受信任模式的系统通过远程处理层传入的以下操作将被忽略:
    • 远程部署 (这也意味着没有远程监控)
    • 远程DeathWatch
    • system.stop(), PoisonPill, Kill
    • 发送任何继承自PossiblyHarmful标记接口的消息,包括Terminated
    • 通过actor selection发送的消息,除非目标定义在trusted-selection-paths中。
  2. 安全 Cookie 握手
    Akka远程处理还允许你指定一个安全cookie,它将被交换并确保在客户端和服务器之间的连接握手中是相同的。如果他们不相同,则客户端将被拒绝连接到服务器。