Artery Remoting

Artery Remoting

注意
远程处理是一种机制,通过这种机制,不同节点上的Actor可以相互通信。
在构建Akka应用程序时,通常不会直接使用Remoting概念,而会使用更高级的Akka Cluster实用程序或与技术无关的协议,例如HTTP,gRPC等。

依赖

要使用Artery Remoting,必须在项目中添加以下依赖项:

Artery UDP依赖Aeron。 如果使用aeron-udp,则需要将其显式添加为依赖项,未使用Artery Remoting的用户的类路径上没有Aeron:

如果要从classic remoting迁移,请查看Artery的新功能

配置

要在Akka项目中启用远程功能,您至少应将以下更改添加到application.conf文件中:

如您在上面的示例中看到的,开始需要添加四件事:

  • 修改local provider。与直接使用远程处理相比,我们建议使用Akka集群。
  • 启用Artery,可以将其用作远程实施
  • 添加主机名-您要在其上运行actor系统的机器;该主机名正是传递给远程系统以识别该系统的名称,因此在需要时可用于连接该系统,因此将其设置为可访问的IP地址或可解析的名称,万一您想通过网络进行通信。
  • 添加端口号-actor系统应侦听的端口,设置为0,以自动设置端口号
注意
即使actor系统具有不同的名称,端口号对于同一台机器上的每个actor系统也必须是唯一的。这是因为每个actor系统都有自己的网络子系统,监听连接并处理消息,以免干扰其他actor系统。

上面的示例仅说明了必须添加才能启用远程处理的最少属性。所有设置在"远程配置"中描述。

介绍

我们建议Akka Cluster优于直接使用远程处理。由于远程处理是支持集群的基础模块,因此了解有关它的细节仍然很有用。

注意
本页描述了Artery远程子系统,该子系统已替代了经典的远程实现。

远程处理使不同主机或JVM上的Actor系统能够相互通信。通过启用远程处理,系统将开始侦听指定的网络地址,并且还具有通过网络连接到其他系统的能力。从应用程序的角度来看,本地系统或远程系统之间没有API区别,指向远程系统的ActorRef实例看起来与本地系统完全相同:它们可以被发送消息,被监视等。每个ActorRef都包含主机名和端口信息,即使在网络上也可以传递ActorRef。这意味着在网络上,每个ActorRef都是该网络上的actor的唯一标识符。

您需要为actor消息启用序列化。在许多情况下,使用Jackson进行序列化是一个不错的选择,如果您没有其他选择,我们建议您这样做。

远程处理不是服务器-客户端技术。如果所有使用远程处理的系统都具有指向该系统的ActorRef,则它们可以联系网络上的任何其他系统。这意味着启用了远程功能的每个系统都充当"服务器",同一网络上的任意系统都可以连接到该服务器。

选择传输协议

有三种使用基础传输的方法。它由属性akka.remote.artery.transport配置,可能的值是:

  • tcp-基于Akka Streams TCP(如果未配置其他则为默认值)
  • tls-tcp-与tcp相同,使用Akka Streams TLS加密
  • aeron-udp-基于Aeron(UDP)

如果不确定如何选择,最好使用默认值tcp。

Aeron(UDP)传输是一种高性能传输,应用于需要高吞吐量和低延迟的系统。当系统处于空闲状态或消息速率较低时,它比TCP使用更多的CPU。 Aeron没有加密。

TCP和TLS传输是使用Akka Streams TCP/TLS实现的。这是需要加密时的选择,但也可以与不带TLS的纯TCP一起使用。当无法使用UDP时,这也是显而易见的选择。它具有非常好的性能(高吞吐量和低延迟),但是高吞吐量下的延迟可能不如Aeron Transport。与Aeron Transport相比,它的操作复杂度更低,并且在容器环境中发生故障的风险也更低。

Aeron要求64位JVM可靠地工作,并且只正式支持Linux,Mac和Windows。它可能在其他Unix上如Solaris运行,但尚未进行充分的测试以使其得到正式支持。如果您使用的是Big Endian处理器(例如Sparc),则建议使用TCP。

注意
从一种传输方式更改为另一种传输方式时,不支持滚动更新。

从经典远程迁移

查阅 migrating from classic remoting

标准地址

为了使远程正常工作,每个系统都可以将消息发送到同一网络上的任何其他系统(例如,系统将消息转发到第三个系统,第三个系统直接答复给发件人系统),每个系统具有唯一的,全球可访问的地址和端口。该地址是系统唯一名称的一部分,其他系统将使用该地址打开与该地址的连接并发送消息。这意味着,如果主机具有多个名称(指向相同IP地址的不同DNS记录),则只有一个可以是标准名称。如果消息到达系统,但包含的主机名与预期的标准名称不同,则该消息将被丢弃。如果允许使用一个系统的多个名称,则将不再信任ActorRef实例之间的相等性检查,这将违反一个基本前提,即一个actor在给定网络上具有全局唯一引用。这也意味着本地地址(例如127.0.0.1)不能被普遍使用(除了本地开发),因为它们不是真实网络中的唯一地址。

在使用网络地址转换(NAT)或涉及其他网络桥接的情况下,为了监听连接,配置系统以使其了解外部可见的规范地址与主机端口对之间存在差异。有关详细信息,请参阅Akka behind NAT or in a Docker container。

获取对远程actor的引用

为了与actor进行交流,必须拥有其ActorRef。在本地情况下,通常是actor的创建者(actorOf()的调用者)为该actor获取ActorRef,然后将其发送给其他actor。换一种说法:

  • Actor可以通过接收来自远程Actor的消息(因为该消息可以通过getSender()获得)或在远程消息内部(例如PleaseReply(message: String, remoteActorRef: ActorRef))获得远程Actor的引用。

或者,actor可以使用ActorSelection查找位于已知路径的另一个actor。这些方法甚至在启用远程的系统中也可用:

  • 远程查找:用于使用actorSelection(path)在远程节点上查找actor
  • 远程创建:用于在具有actorOf(Props(...),actorName)的远程节点上创建actor

在下一节中,将详细介绍这两种选择。

查找远程actor

actorSelection(path)将获得一个ActorSelection到远程节点上的Actor,例如:

从上面的示例中可以看到,以下模式用于在远程节点上查找actor:

注意
与早期的远程处理不同,协议字段始终为akka,因为不再支持可插拔传输。

选择actor后,您可以使用与本地actor相同的方式与之交互,例如:

要为ActorSelection获取ActorRef,您需要向selection发送一条消息,并使用来自actor的回复的发送者引用。有一个内置的标识消息,所有Actor都会理解该消息,并自动通过包含ActorRef的ActorIdentity消息进行回复。也可以使用ActorSelection的resolveOne方法来完成,该方法返回匹配的ActorRef的Future。

有关Actor地址和路径的形成和使用方式的更多详细信息,请参阅Actor参考,路径和地址。

注意
不会通过远程actor ref提供程序,向发送actor系统中的actor的发送消息。它们是由本地actor引用提供者直接交付的。
除了提供更好的性能外,这还意味着,如果无法在完全相同的actor系统中解析您配置的监听主机名,则可以(也许违反直觉)传递此类消息。

远程安全

ActorSystem不应通过Akka Remote(Artery)通过普通的Aeron/UDP或TCP暴露给不受信任的网络(例如Internet)。 它应该受到网络安全性(例如防火墙)的保护。 如果没有足够的保护,则应启用具有双向身份验证的TLS。

最佳实践是Akka远程处理节点只能从相邻网络访问。 请注意,如果通过相互身份验证启用了TLS,则攻击者仍有可能通过使用由同一内部PKI树颁发的证书破坏任何节点,来获得对有效证书的访问权。

默认情况下,在Akka中禁用Java序列化。 由于它具有多个已知的攻击面,因此这也是安全性最佳实践。

配置SSL/TLS以进行Akka远程处理

通过使用tls-tcp传输,将SSL用作远程传输:

接下来,必须配置实际的SSL/TLS参数:

始终使用环境变量来代替密码。不要在配置文件中定义真实密码。

根据RFC 7525,建议与TLS 1.2一起使用的算法(撰写本文时)为:

  • TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

在配置系统之前,您应该始终检查有关安全性和算法建议的最新信息。

Lightbend的SSL-Config库的"生成X.509证书"部分详细记录了创建和使用密钥库和证书的过程。

由于Akka远程处理本质上是对等的,因此需要在参与集群的每个远程处理节点上配置密钥存储和信任存储。

官方Java Secure Socket Extension文档以及有关创建KeyStore和TrustStore的Oracle文档都是在JVM上设置安全性时研究的重要资源。在对SSL进行故障排除和配置时,请查阅这些资源。

TLS对等方之间的相互身份验证默认情况下处于启用状态。相互认证意味着连接的被动方(TLS服务器方)也将请求并验证连接对等方的证书。如果没有此模式,则仅客户端在请求和验证证书。虽然Akka是点对点技术,但节点之间的每个连接都从一侧("客户端")开始到另一侧("服务器")。

请注意,如果通过相互身份验证启用了TLS,则攻击者仍有可能通过使用由同一内部PKI树颁发的证书破坏任何节点来获得对有效证书的访问权。

建议您通过akka.remote.artery.ssl.config-ssl-engine.hostname-verification = on启用主机名验证。启用后,它将验证目标主机名是否与对等方证书中的主机名匹配。

在主机名是动态的且事先不知道的部署中,可以取消主机名验证。

您可以选择几种方式来设置证书和主机名验证:

  • 所有节点具有一套密钥和一个证书,并禁用主机名检查

    • 单个密钥集和单个证书分配给所有节点。证书可以自签名,因为它既作为身份验证证书分发,也作为受信任证书分发。
    • 如果密钥/证书丢失,其他人可以连接到您的群集。
    • 将节点添加到集群很简单,因为可以将关键material部署/分发到新节点。
  • 包含所有主机名的所有节点,具有一套密钥和一个证书,并启用主机名检查。

    • 这意味着只有证书中提到的主机才能连接到群集。
    • 如果要与之交谈的节点是它应该是的节点(或者它是其他节点之一),则无法检查它。这似乎是一个较小的限制,因
      为无论如何您必须信任Akka群集中的所有群集节点。
    • 证书可以是自签名的,在这种情况下,相同的单个证书可以在所有节点上分发和信任(但请参阅下一个项目符号)
    • 添加新节点意味着其主机名需要与证书中的受信任主机名一致。这要么意味着预见新主机,要么首先使用通配符证书,要么首先使 用完整的CA,因此,如果要添加更多的节点,则可以稍后颁发更多的证书(但是您已经进入下一个解决方案的领域了)。
    • 如果证书被盗,则只能用于通过可信任证书中的主机名从可访问的节点连接到群集。这将需要篡改DNS,以允许其他节点访问群集(但是,在内部设置中篡改DNS可能比在Internet规模上更容易)。
  • 为每个节点设置一个CA,密钥/证书,并启用主机名检查。

    • 基本上像Internet HTTPS一样,但是您只信任内部CA,然后为每个新节点颁发证书。
    • 需要一个PKI,CA证书在所有节点上都是受信任的,各个证书用于身份验证。
    • 仅分发CA证书和节点的密钥/证书。
    • 如果密钥/证书被盗,则只有同一节点可以访问群集(除非DNS也被篡改)。您可以撤消单个证书。

另请参阅"远程配置"部分中的设置说明。

注意
在Linux上使用SHA1PRNG时,建议将-Djava.security.egd=file:/dev/urandom指定为JVM的参数,以防止阻塞。它不那么安全,因为它会重用种子。

不信任模式

一个actor系统一旦可以远程连接到另一个系统,则原则上可以将任何可能的消息发送到该远程系统中包含的任何actor。一个示例可能是将PoisonPill发送给系统守护者,从而关闭了该系统。并非总是如此,可以使用以下设置禁用它:

这不允许发送系统消息(actor生命周期命令,DeathWatch等)以及任何扩展PossibleHarmful的消息。但是,如果客户端发送了它们,则它们将被丢弃并记录下来(处于DEBUG级别,以减少拒绝服务攻击的可能性)。 "PossiblyHarmful"涵盖了诸如PoisonPill和Kill之类的预定义消息,但也可以将其作为标记接口添加到用户定义的消息中。

警告
不受信任的模式不能完全保护自己免受攻击。它使执行恶意或意外动作的难度稍大一些,但应注意,仍不应启用Java序列化。当在不受信任的网络中运行时,可以通过网络安全性(例如防火墙)和/或启用具有相互身份验证的TLS来获得额外的保护。

默认情况下,使用actor selection 发送的消息在不受信任的模式下被丢弃,但是可以将接收actor selection 消息的权限授予配置中定义的特定actor:

实际消息仍不能为PossibleHarmful类型。

总之,当通过远程处理层传入时,以非信任模式配置的系统将忽略以下操作:

  • 远程部署(这也意味着没有远程监管)
  • 远程DeathWatch
  • system.stop(),PoisonPill, Kill
  • 发送扩展PossiblyHarmful接口的任何消息,包括Terminated
  • 除非已在trusted-selection-paths中定义了目的地,否则使用actor selection发送的消息。
注意
启用不信任模式不会删除客户端自由选择其消息发送目标的功能,这意味着可以将上述规则未禁止的消息发送给远程系统中的任何actor。面向客户的系统的良好做法是仅包含一组定义明确的入口点actor,然后将请求(可能在执行验证之后)转发到包含实际工作者actor的另一个actor系统。如果这两个服务器端系统之间的消息传递是使用本地ActorRef完成的(可以在同一JVM中的actor系统之间安全地交换它们),则可以通过在消息接口上标记"PossiblyHarmful"来限制消息,以使客户端无法伪造消息。

隔离

Akka远程处理将Aeron用作底层消息传输。 Aeron使用UDP,还添加了可靠的传递和会话语义,这与TCP非常相似。这意味着将保留消息的顺序,这是Actor消息顺序保证所必需的。在正常情况下,所有消息都将被传递,但是在某些情况下,可能无法将消息传递到目的地:

  • 在网络分区和Aeron会话中断期间,一旦分区结束,此操作将自动恢复
  • 当发送太多消息而没有流控制,塞满出站发送队列时(outbound-message-queue-size配置)
  • 如果消息的序列化或反序列化失败(只会丢掉该消息)
  • 如果远程处理发生意外的异常

简而言之,如消息传递可靠性中所述,Actor消息传递是"最多一次"

Akka中的某些消息称为系统消息,不能删除这些消息,因为这会导致系统之间的状态不一致。这些消息主要用于两个功能:远程死亡监视和远程部署。这些消息由Akka远程处理传递,通过确认每条消息并重新发送未确认的消息实现"完全一次"保证。如果仍然无法传递系统消息,则与目标系统的关联将无法恢复,并且将向远程系统上的所有受监视的actor发出终止消息。它处于所谓的隔离状态。如果不使用远程监视或远程部署,通常不会发生隔离。

每个ActorSystem实例都有一个唯一的标识符(UID),这对于重新启动系统时,区分具有相同主机和端口的系统很重要。被隔离的是特定的(UID)。从此状态恢复的唯一方法是重新启动其中一个actor系统。

发送到隔离系统和从隔离系统接收的消息将被丢弃。但是,可以使用actorSelection将消息发送到隔离系统的地址,这对于探测系统是否已重新启动很有用。

在以下情况下,将隔离关联:

  • 集群节点已从群集成员关系中删除。
  • 远程故障检测器触发器,即使用远程监视。使用Akka集群时,这是不同的。如果网络分区修复,则集群故障检测器无法进行的观察可以恢复到可以进行的状态。故障检测器触发时,集群成员未隔离。
  • 系统消息传递缓冲区溢出,例如因为同时有太多监视请求(system-message-buffer-size)。
  • 远程系统的控制子通道中发生异常。

当第一个消息发送到目的地时,ActorSystem的UID在双向握手中进行交换。握手将重试,直到其他系统答复为止,直到握手完成,其他消息都不会通过。如果无法在超时(握手超时配置)内建立握手,则关联将停止(释放资源)。如果无法建立握手,则排队的消息将被丢弃。由于UID未知,因此不会被隔离。当下一条消息发送到目的地时,新的握手尝试将开始。

实际上,还会在目标系统重新启动后定期发送握手请求,以建立工作连接。

监控远程actor

监控远程actor就像监控本地actor一样,如Lifecycle Monitoring或DeathWatch中所述。但是,需要注意的是,与本地情况不同,当远程actor不能以一种优雅的方式终止,发送系统消息以通知观察者actor有关事件,而是将其托管在一个突然停止的系统。这些情况由内置的故障检测器处理。

故障检测

在后台,远程死亡监视程序除了正常终止受监视的actor之外,还使用心跳消息和故障检测器从网络故障和JVM崩溃生成终止消息。

心跳到达时间由Phi应计故障检测器解释。

失败的可疑程度由称为phi的值给出。 phi故障检测器的基本思想是在可以动态调整以反映当前网络状况的标度上,表达phi的值。

phi的值计算如下:

其中F是正态分布的累积分布函数,其均值和标准差是根据历史心跳到达间隔时间估算得出的。

在远程配置中,您可以调整akka.remote.watch-failure-detector.threshold来定义何时将phi值视为失败。

较低的阈值易于产生许多误报,但可以确保在发生实际碰撞时快速检测到。 相反,较高的阈值产生较少的错误,但需要更多的时间来检测实际的崩溃。 默认阈值为10,适用于大多数情况。 但是,在诸如Amazon EC2之类的云环境中,该值可以增加到12,以解决有时在此类平台上发生的网络问题。

下图说明了自上一个心跳以来phi如何随着时间增加而增加。
Artery Remoting_第1张图片

根据历史到达时间的平均值和标准偏差计算出Phi。上一张图表是200 ms标准偏差的示例。如果心跳以较小的偏差到达,则曲线会变陡,即可以更快地确定故障。对于100 ms的标准偏差,曲线看起来像这样。

Artery Remoting_第2张图片

为了能够应对突发异常(例如垃圾收集暂停和瞬态网络故障),故障检测器配置有余量akka.remote.watch-failure-detector.acceptable-heartbeat-pause。您可能要根据您的环境调整此功能的"远程配置"。这是配置为3秒的"acceptable-heartbeat-pause"曲线的样子。

Artery Remoting_第3张图片

序列化

您需要为actor消息启用序列化。在许多情况下,使用Jackson进行序列化是一个不错的选择,如果您没有其他选择,我们建议使用。

基于ByteBuffer的序列化

Artery引入了一种新的序列化机制,该机制允许ByteBufferSerializer直接写入共享的java.nio.ByteBuffer,而不必为每个序列化的消息分配并返回Array[Byte]。对于高吞吐量消息传递,此API更改可以带来显着的性能优势,因此我们建议更改序列化程序以使用此新机制。

这个新的API还可以与新版本的Google Protocol Buffers和其他序列化库一起很好地使用,它们具有直接与ByteBuffers进行串行化的功能。

由于新功能仅更改字节的读取和写入方式,而其余序列化基础结构保持不变,因此我们建议您先阅读序列化文档。

实现akka.serialization.ByteBufferSerializer的方式与其他任何序列化器相同。

因此,为Artery实现序列化程序与实现此接口一样简单,并像往常一样绑定序列化程序(在序列化中进行了说明)。

实现通常应扩展SerializerWithStringManifest,除了基于ByteBuffer的toBinary和fromBinary方法之外,还应实现基于数组的toBinary和fromBinary方法。 当不使用ByteBuffer时将使用基于数组的方法,例如 在Akka Persistence中。

请注意,基于数组的方法可以通过委派来实现,如下所示:

带有远程目标的路由器

将远程处理与路由相结合是绝对可行的。

远程部署路由池可以配置为:

此配置设置将克隆remotePool的Props中定义的actor 10次,并将其均匀分布在两个给定的目标节点上。

使用远程部署的路由池时,必须确保可以对Props的所有参数进行序列化。

一组远程actor可以配置为:

此配置会将消息发送到已定义的远程actor路径。它要求您在具有匹配路径的远程节点上创建目标actor。这不是由路由器完成的。

Artery的新变化

Artery是旧远程模块的重新实现,旨在提高性能和稳定性。它在很大程度上与旧的实现兼容,并且在许多情况下是直接替代。与之前的实现相比,Artery的主要功能:

  • 基于Aeron(UDP)和Akka Streams TCP/TLS而不是Netty TCP
  • 专注于高吞吐量,低延迟的通信
  • 通过使用专用子通道,可以将内部控制消息与用户消息隔离开来,从而提高了稳定性并减少了在流量较大时的错误故障检测。
  • 主要是无分配操作
  • 支持大消息的单独子信道,以避免干扰小消息
  • 压缩线上的actor路径以减少较小消息的开销
  • 直接使用ByteBuffer支持更快的序列化/反序列化
  • 内置的Flight-Recorder可帮助调试实施问题,而不会因实施特定事件而污染用户日志
  • 提供主要Akka版本之间的协议稳定性,以支持大规模系统的滚动更新

与以前的实现的主要不兼容变化是ActorRef的字符串表示形式的协议字段始终为akka,而不是先前使用的akka.tcp或akka.ssl.tcp。配置属性也不同。

性能调优

通道

消息序列化和反序列化可能是远程通信的瓶颈。因此,支持并行的入站和出站通道以并行执行序列化和其他任务,以供不同的目标actor使用。对于入站消息,使用多个通道最有价值,因为来自所有远程系统的所有入站消息共享同一入站流。对于出站消息,每个远程目标系统已经有一个流,因此,多个出站通道仅在发送到同一目标系统中的不同actor时才增加价值。

通道的选择基于接收者ActorRef的一致哈希值,以保留每个接收者的消息顺序。

注意,入站通道数= 1和出站通道数= 1可以实现最低的延迟,因为多个通道引入了异步边界。

还要注意,并行任务的总数受remote-dispatcher的约束,并且线程池的大小不应超过CPU核心数减去实际在应用程序中处理消息的,实际上pool的大小应小于核心数量的一半。

有关默认值,请参见参考配置中的入站通道和出站通道。

大消息专用子通道

用户定义的远程actor之间的所有通信均与Akka内部消息的通道隔离,因此,较大的用户消息不能阻塞紧急系统消息。虽然这为Akka服务提供了良好的隔离,但是默认情况下,所有用户通信都是通过共享网络连接(Aeron流)进行的。当一些actor发送大消息时,这可能导致其他消息遭受更高的延迟,因为他们需要等待直到完整消息已在共享通道上传输(因此成为共享瓶颈)。在这些情况下,分离具有不同QoS要求的actor通常是有帮助的:大消息与低延迟。

Akka远程处理(如果已配置)为大型消息提供了专用通道。由于一定不能违反actor消息的顺序,因此该通道实际上专用于actor而不是消息,以确保所有消息都按发送顺序到达。通过使用必须在发送方和接收方的actor系统配置中指定的路径模式,可以在给定路径上分配actor以使用此专用通道:

conf
这意味着发送给以下actor的所有消息都将通过专用的大型消息通道传递:

-/user/largeMessageActor
-/user/largeMesageActorGroup/actor1
-/user/largeMessageActorGroup/actor2
-/user/anotherGroup/actor1/largeMes​​sages
-/user/anotherGroup/actor2/largeMes​​sages
-/user/thirdGroup/actor3/
-/user/thirdGroup/actor4/actor5

如前所述,使用默认通道发送发往与这些模式都不匹配的actor的消息。

外部共享的Aeron媒体驱动程序

Aeron传输在所谓的media driver中运行。默认情况下,Akka启动与应用程序相同的JVM进程中嵌入的媒体驱动程序。这很方便,并且只需一个进程即可启动和监视,从而简化了操作问题。

media驱动程序可能会占用大量CPU资源。如果在同一台机器上运行多个Akka应用程序JVM,则明智的做法是将其作为单独的进程运行,以共享媒体驱动程序。

媒体驱动程序还具有与普通应用程序不同的资源使用特性,因此,将媒体驱动程序作为单独的进程运行会更加高效和稳定。

鉴于Aeron jar文件位于类路径中,可以使用以下方式启动独立的媒体驱动程序:

需要的classpath

您可以在Maven Central上找到这些jar文件,也可以使用首选的构建工具创建一个包。

您可以将Aeron属性作为命令行-D系统属性传递:

您还可以在文件中定义Aeron属性:

此类属性文件的示例:

在Aeron文档中了解有关媒体驱动程序的更多信息。

要使用Akka应用程序中的外部媒体驱动程序,您需要定义以下两个配置属性:

aeron-dir必须与您启动媒体驱动程序时使用的目录匹配,即aeron.dir属性。

然后,可以通过指向同一目录将多个Akka应用程序配置为使用相同的媒体驱动程序。

请注意,如果媒体驱动程序进程已停止,则正在使用该进程的Akka应用程序也将停止。

Aeron调优

请参阅有关性能测试的Aeron文档。

微调CPU使用率延迟权衡

Artery 设计用于低延迟,因此,当系统大部分处于空闲状态时,它可能会占用大量CPU。这并不总是可取的。使用Aeron传输时,可以通过以下配置在CPU使用率和延迟之间进行权衡:
conf
通过将此值设置为较小的数字,它告诉Akka在专用于自旋等待的线程上执行更长的"休眠"时间段,从而在没有立即执行的任务的情况下减少CPU负载,但代价是对实际发生的事件响应时间更长。值得一提的是,在连续的高吞吐量期间,此设置没有太大的区别,因为线程主要执行任务。这也意味着在高吞吐量(但低于最大容量)下,系统的延迟可能比低消息速率下的延迟少。

远程配置

有许多与Akka中的远程处理相关的配置属性。我们参考reference configuration以获取更多信息。

注意
最好以编程方式设置诸如侦听IP和端口号之类的属性,方法如下:

NAT或Docker容器中的Akka

在涉及网络地址转换(NAT),负载均衡器或Docker容器的设置中,Akka绑定到的主机名和端口对将不同于用于从外部连接到系统的"逻辑"主机名和端口对。这需要特殊的配置,该配置同时设置逻辑对和绑定对以进行远程处理。
conf
您可以查看带有docker-compse的示例项目集群,以了解实际情况。

在Docker/Kubernetes中运行

在容器化环境中使用aeron-udp时,必须特别注意媒体驱动程序在ram磁盘上运行。默认情况下,它位于/dev/shm中,在大多数物理Linux机器上,它将被挂载为系统内存大小的一半。

Docker和Kubernetes挂载了一个64Mb的ram磁盘。这不太可能足够大。对于docker,可以使用--shm-size ="512mb"覆盖。

在Kubernetes中,尚无直接支持来设置shm大小。而是将一个Memory类型的EmptyDir挂载到/dev/shm中,例如在一个deployment.yml中:
yml

当前没有办法限制内存空目录的大小,但是有添加的pull request 。

挂载中使用的所有空间都将计入容器的内存使用量。

飞行记录仪

在JDK 11 上运行Artery时,可通过Java Flight Recorder(JFR)获得特定的飞行记录。通过检测JDK 11可以自动启用飞行记录器,但可以通过设置akka.java-flight-recorder.enabled=false禁用飞行记录器。

启用JFR时,默认情况下会发出开销较低的Artery特定事件,开销较高的事件需要自定义设置模板,并且不会通过分析JFR模板自动启用。要启用这些功能,请创建概要分析模板的副本并启用所有Akka子类别事件,例如通过JMC GUI。

你可能感兴趣的:(vue.js)