kka-typed(5) - cluster:集群节点状态监视
akka-cluster对每个节点的每种状态变化都会在系统消息队列里发布相关的事件。通过订阅有关节点状态变化的消息就可以获取每个节点的状态。这部分已经在之前关于akka-cluster的讨论里介绍过了。由于akka-typed里采用了新的消息交流协议,而系统消息的发布和订阅也算是消息交换,也受交流协议约束。所以想通过重写以前示范的ClusterMemberStatus来了解一下akka-typed环境下节点状态变化消息监听的一些机制。
我们需要一个actor来订阅系统发布的节点状态变化消息。这里涉及到系统、actor两端的信息交流。假设向系统订阅是一种消息的发送,那么得到的节点状态变化消息就是系统的response了。先看看actor里的消息定义:
object MonitorActor {
sealed trait ClusterEvent
private case class MemberStatus(event: MemberEvent) extends ClusterEvent
private case class ReachStatus(event: ReachabilityEvent) extends ClusterEvent
def apply(): Behavior[ClusterEvent] = Behaviors.setup[ClusterEvent] { ctx =>
val memberEventAdapter: ActorRef[MemberEvent] = ctx.messageAdapter(MemberStatus)
val reachEventAdapter: ActorRef[ReachabilityEvent] = ctx.messageAdapter(ReachStatus)
Cluster(ctx.system).subscriptions ! Subscribe(memberEventAdapter,classOf[MemberEvent])
Cluster(ctx.system).subscriptions ! Subscribe(reachEventAdapter,classOf[ReachabilityEvent])
...
}
首先,response 分为 MemberEvent, ReachabilityEvent两种。MonitorActor处理的消息类型是ClusterEvent。为了处理系统返回的response类型,即MemberEvent,ReachabilityEvent,必须提供这两种类型到ClusterEvent的转换。通过ctx.messageAdapter登记MemberEvent -> MemberStatus, ReachabilityEvent -> ReachStatus两种类型转换机制使MonitorActor可以接收到MemberStatus, ReachStatus两种消息:
object MonitorActor {
sealed trait ClusterEvent
private case class MemberStatus(event: MemberEvent) extends ClusterEvent
private case class ReachStatus(event: ReachabilityEvent) extends ClusterEvent
def apply(): Behavior[ClusterEvent] = Behaviors.setup[ClusterEvent] { ctx =>
val memberEventAdapter: ActorRef[MemberEvent] = ctx.messageAdapter(MemberStatus)
val reachEventAdapter: ActorRef[ReachabilityEvent] = ctx.messageAdapter(ReachStatus)
Cluster(ctx.system).subscriptions ! Subscribe(memberEventAdapter,classOf[MemberEvent])
Cluster(ctx.system).subscriptions ! Subscribe(reachEventAdapter,classOf[ReachabilityEvent])
Behaviors.receiveMessage { event =>
event match {
case MemberStatus(status) =>
status match {
case MemberJoined(member) =>
ctx.log.info("**************** Member joined: [{}] ***************", member.address)
case MemberJoined(member) =>
ctx.log.info("**************** Member joined: [{}] ***************", member.address)
case MemberUp(member) =>
ctx.log.info("**************** Member is Up: [{}] ***************", member.address)
case MemberRemoved(member, previousStatus) =>
ctx.log.info("**************** Member is Removed: [{}] after {} ***************",
member.address, previousStatus)
case MemberLeft(member) =>
ctx.log.info("**************** Member left: [{}] ***************", member.address)
case MemberExited(member) =>
ctx.log.info("**************** Member exited: [{}] ***************", member.address)
case _: MemberEvent => // ignore
}
case ReachStatus(status) =>
status match {
case UnreachableMember(member) =>
ctx.log.info("**************** Member detected as unreachable: [{}] ***************", member)
case ReachableMember(member) =>
ctx.log.info("**************** Member back to reachable: [{}] ***************", member)
}
}
Behaviors.same
}
}
}
还需要一个actor, 什么都不干。存粹构建一个MonitorActor:
object RootActor {
def apply(): Behavior[Nothing] = Behaviors.setup[Nothing] {ctx =>
ctx.spawn(MonitorActor(),"listner")
Behaviors.empty
}
}
好了,看看main是怎么实现的吧:
object ClusterMemberStatus {
import com.typesafe.config.ConfigFactory
def main(args: Array[String]): Unit = {
val ports =
if (args.isEmpty)
Seq(, , )
else
args.toSeq.map(_.toInt)
ports.foreach { port =>
startup(port)
}
}
def startup(port: Int): Unit = {
val config = ConfigFactory.parseString(s"""
akka.remote.artery.canonical.port=$port
""").withFallback(ConfigFactory.load("cluster.conf"))
ActorSystem[Nothing](RootActor(),"ClusterSystem",config)
}
}
下面是测试结果显示:
::52.755 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25251] ***************
::52.810 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:51081] - Received InitJoinAck message from [Actor[akka://ClusterSystem@127.0.0.1:25251/system/cluster/core/daemon#313431252]] to [akka://ClusterSystem@127.0.0.1:51081]
::52.825 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Node [akka://ClusterSystem@127.0.0.1:51081] is JOINING, roles [dc-default]
::52.825 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member joined: [akka://ClusterSystem@127.0.0.1:51081] ***************
::52.829 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:25251] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:51081,567025403336682144)]
::52.858 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:51081] - Welcome from [akka://ClusterSystem@127.0.0.1:25251]
::52.858 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25251] ***************
::52.858 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member joined: [akka://ClusterSystem@127.0.0.1:51081] ***************
::52.858 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:51081] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:25251,6076326462170320177)]
::53.044 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Leader is moving node [akka://ClusterSystem@127.0.0.1:51081] to [Up]
::53.044 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:51081] ***************
::53.679 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:51081] ***************
::57.707 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Received InitJoin message from [Actor[akka://ClusterSystem@127.0.0.1:25252/system/cluster/core/daemon/joinSeedNodeProcess-1#1472023843]] to [akka://ClusterSystem@127.0.0.1:25251]
::57.707 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Sending InitJoinAck message from node [akka://ClusterSystem@127.0.0.1:25251] to [Actor[akka://ClusterSystem@127.0.0.1:25252/system/cluster/core/daemon/joinSeedNodeProcess-1#1472023843]] (version [2.6.5])
::57.732 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25252] - Received InitJoinAck message from [Actor[akka://ClusterSystem@127.0.0.1:25251/system/cluster/core/daemon#313431252]] to [akka://ClusterSystem@127.0.0.1:25252]
::57.734 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Node [akka://ClusterSystem@127.0.0.1:25252] is JOINING, roles [dc-default]
::57.735 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member joined: [akka://ClusterSystem@127.0.0.1:25252] ***************
::57.735 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:25251] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:25252,-6913064885699273532)]
::57.737 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25252] - Welcome from [akka://ClusterSystem@127.0.0.1:25251]
::57.737 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25251] ***************
::57.738 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:25252] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:25251,6076326462170320177)]
::57.738 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member joined: [akka://ClusterSystem@127.0.0.1:25252] ***************
::57.738 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:51081] ***************
::57.738 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:25252] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:51081,567025403336682144)]
::57.740 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member joined: [akka://ClusterSystem@127.0.0.1:25252] ***************
::57.740 [ClusterSystem-akka.actor.internal-dispatcher-] DEBUG akka.cluster.typed.internal.receptionist.ClusterReceptionist - ClusterReceptionist [akka://ClusterSystem@127.0.0.1:51081] - Node added [UniqueAddress(akka://ClusterSystem@127.0.0.1:25252,-6913064885699273532)]
::58.134 [ClusterSystem-akka.actor.default-dispatcher-] INFO akka.cluster.Cluster - Cluster Node [akka://ClusterSystem@127.0.0.1:25251] - Leader is moving node [akka://ClusterSystem@127.0.0.1:25252] to [Up]
::58.134 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25252] ***************
::58.755 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25252] ***************
::59.146 [ClusterSystem-akka.actor.default-dispatcher-] INFO com.learn.akka.MonitorActor$ - **************** Member is Up: [akka://ClusterSystem@127.0.0.1:25252] ***************
下面是本次示范的全部源代码:
build.sbt
name := "learn-akka-typed" version := "0.1" scalaVersion := "2.13.1"
scalacOptions in Compile ++= Seq("-deprecation", "-feature", "-unchecked", "-Xlog-reflective-calls", "-Xlint")
javacOptions in Compile ++= Seq("-Xlint:unchecked", "-Xlint:deprecation") val AkkaVersion = "2.6.5"
val AkkaPersistenceCassandraVersion = "1.0.0" libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-cluster-sharding-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-persistence-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-persistence-query" % AkkaVersion,
"com.typesafe.akka" %% "akka-serialization-jackson" % AkkaVersion,
"com.typesafe.akka" %% "akka-persistence-cassandra" % AkkaPersistenceCassandraVersion,
"com.typesafe.akka" %% "akka-slf4j" % AkkaVersion,
"ch.qos.logback" % "logback-classic" % "1.2.3"
)
cluster.conf
akka {
actor {
provider = cluster
serialization-bindings {
"com.learn.akka.CborSerializable" = jackson-cbor
}
}
remote {
artery {
canonical.hostname = "127.0.0.1"
canonical.port =
}
}
cluster {
seed-nodes = [
"akka://ClusterSystem@127.0.0.1:25251",
"akka://ClusterSystem@127.0.0.1:25252"]
}
}
ClusterMemberStatus.scala
package com.learn.akka
import akka.actor.typed._
import akka.actor.typed.scaladsl.Behaviors
import akka.cluster.ClusterEvent._
import akka.cluster.typed.Subscribe
import akka.cluster.typed.Cluster
import akka.actor.typed.ActorSystem object MonitorActor {
sealed trait ClusterEvent
private case class MemberStatus(event: MemberEvent) extends ClusterEvent
private case class ReachStatus(event: ReachabilityEvent) extends ClusterEvent def apply(): Behavior[ClusterEvent] = Behaviors.setup[ClusterEvent] { ctx =>
val memberEventAdapter: ActorRef[MemberEvent] = ctx.messageAdapter(MemberStatus)
val reachEventAdapter: ActorRef[ReachabilityEvent] = ctx.messageAdapter(ReachStatus)
Cluster(ctx.system).subscriptions ! Subscribe(memberEventAdapter,classOf[MemberEvent])
Cluster(ctx.system).subscriptions ! Subscribe(reachEventAdapter,classOf[ReachabilityEvent])
Behaviors.receiveMessage { event =>
event match {
case MemberStatus(status) =>
status match {
case MemberJoined(member) =>
ctx.log.info("**************** Member joined: [{}] ***************", member.address)
case MemberJoined(member) =>
ctx.log.info("**************** Member joined: [{}] ***************", member.address)
case MemberUp(member) =>
ctx.log.info("**************** Member is Up: [{}] ***************", member.address)
case MemberRemoved(member, previousStatus) =>
ctx.log.info("**************** Member is Removed: [{}] after {} ***************",
member.address, previousStatus)
case MemberLeft(member) =>
ctx.log.info("**************** Member left: [{}] ***************", member.address)
case MemberExited(member) =>
ctx.log.info("**************** Member exited: [{}] ***************", member.address)
case _: MemberEvent => // ignore
}
case ReachStatus(status) =>
status match {
case UnreachableMember(member) =>
ctx.log.info("**************** Member detected as unreachable: [{}] ***************", member)
case ReachableMember(member) =>
ctx.log.info("**************** Member back to reachable: [{}] ***************", member)
}
}
Behaviors.same
}
}
}
object RootActor {
def apply(): Behavior[Nothing] = Behaviors.setup[Nothing] {ctx =>
ctx.spawn(MonitorActor(),"listner")
Behaviors.empty
}
}
object ClusterMemberStatus {
import com.typesafe.config.ConfigFactory
def main(args: Array[String]): Unit = {
val ports =
if (args.isEmpty)
Seq(, , )
else
args.toSeq.map(_.toInt)
ports.foreach { port =>
startup(port)
} } def startup(port: Int): Unit = {
val config = ConfigFactory.parseString(s"""
akka.remote.artery.canonical.port=$port
""").withFallback(ConfigFactory.load("cluster.conf"))
ActorSystem[Nothing](RootActor(),"ClusterSystem",config)
} }
kka-typed(5) - cluster:集群节点状态监视的更多相关文章
- Redis Cluster 集群节点维护 (三)
Redis Cluster 集群节点维护: 集群运行很久之后,难免由于硬件故障,网络规划,业务增长,等原因对已有集群进行相应的调整,比如增加redis nodes 节点,减少节点,节点迁移,更换服务器 ...
- Redis Cluster 集群节点信息 维护篇(二)
集群信息文件: # cluster 集群内部信息对应文件,由集群自动维护. /data/soft/redis/6379data/nodes-6379.conf 集群信息查看: ./redis-trib ...
- k8s 集群 节点状态显示notready
一般情况下 我们是在maste节点上安装网络插件的,然后在join node 节点,这样导致node节点可能无法加载到这些插件 使用 journalctl -f -u kubelet 显示如下内容 N ...
- MongoDB分片集群节点状态stateStr:RECOVERING解决
1.关闭一直处于RECOVERING状态的mongodb server /opt/mongodb/mongodb-linux-x86_64-2.4.8/bin/mongo 127.0.0.1:220 ...
- Redis搭建(七):Redis的Cluster集群动态增删节点
一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cluste ...
- Redis进阶实践之十二 Redis的Cluster集群动态扩容
一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cl ...
- centos6下redis cluster集群部署过程
一般来说,redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口,比如:slaveof 192.168.10.10 6379,然后启动主从,主从 ...
- Jedis cluster集群初始化源码剖析
Jedis cluster集群初始化源码剖析 环境 jar版本: spring-data-redis-1.8.4-RELEASE.jar.jedis-2.9.0.jar 测试环境: Redis 3.2 ...
- Redis Cluster 集群使用(3)
简介 Redis3.0版本之前,可以通过Redis Sentinel(哨兵)来实现高可用(HA),从3.0版本之后,官方推出了Redis Cluster,它的主要用途是实现数据分片(Data Shar ...
随机推荐
- 力扣题解-LCP 06. 拿硬币
题目描述 桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中.我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数. 示例 1: 输入:[4,2,1] 输出:4 解释: ...
- class.getFields和class.getDeclareFields的区别
class.getFields的定义 返回类提供的public域包括超类的共有变量; 注: 是public,我们平时定义变量一般用的private,如果用getFields是不会获得. class.g ...
- MySQL事务及实现、隔离级别及锁与优化
事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.事务是逻辑上的一组操作,要么都执行,要么都不执行. ACID简介 原子性(Atomicity) ...
- 重学 Java 设计模式:实战工厂方法模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 牛客网挑战赛19 B,C,F
链接:https://www.nowcoder.com/acm/contest/131/B来源:牛客网 矩阵 M 包含 R 行 C 列,第 i 行第 j 列的值为 Mi,j. 请寻找一个子矩阵,使得这 ...
- Hyperledger Fabric开发(一):环境配置
macOS系统下配置hyperledger fabric环境 cURL mac中自带curl,如果需要下载最新版本,则可按照以下命令,并将路径添加在系统环境变量的最前面即可 brew install ...
- VMware Workstation如何修改弹出释放快捷键
VMware Workstation默认使用Ctrl+Alt键就可以将鼠标从虚拟机脱离出来. 但有时这2个键可能会和其他软件的快捷键冲突,这时候如何设置快捷键呢: 打开WMware Workstati ...
- Redis数据迁移同步工具(redis-shake)
前言 最近线上一台自建redis服务的服务器频繁报警,内存使用率有点高,这是一台配置比较简陋(2C8G)的机子了,近期也打算准备抛弃它了.抛弃之前需对原先的数据进行迁移,全量数据,增量数据都需要考虑, ...
- CopyOnWriteArrayList(写入并复制) & CountDownLatch(闭锁)
ConcurrentHashMap: ①Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器 的性能.② ConcurrentHashMap 同步容器 ...
- Python数据科学利器
每个工具都带有用来创造它的那种精神. -- 海森堡<物理学和哲学> Anaconda Anaconda是一个python的科学计算发行版,其附带了一大批常用的数据科学包,不用再使用pip安 ...