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:集群节点状态监视的更多相关文章

  1. Redis Cluster 集群节点维护 (三)

    Redis Cluster 集群节点维护: 集群运行很久之后,难免由于硬件故障,网络规划,业务增长,等原因对已有集群进行相应的调整,比如增加redis nodes 节点,减少节点,节点迁移,更换服务器 ...

  2. Redis Cluster 集群节点信息 维护篇(二)

    集群信息文件: # cluster 集群内部信息对应文件,由集群自动维护. /data/soft/redis/6379data/nodes-6379.conf 集群信息查看: ./redis-trib ...

  3. k8s 集群 节点状态显示notready

    一般情况下 我们是在maste节点上安装网络插件的,然后在join node 节点,这样导致node节点可能无法加载到这些插件 使用 journalctl -f -u kubelet 显示如下内容 N ...

  4. MongoDB分片集群节点状态stateStr:RECOVERING解决

    1.关闭一直处于RECOVERING状态的mongodb server /opt/mongodb/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:220 ...

  5. Redis搭建(七):Redis的Cluster集群动态增删节点

    一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cluste ...

  6. Redis进阶实践之十二 Redis的Cluster集群动态扩容

    一.引言     上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cl ...

  7. centos6下redis cluster集群部署过程

    一般来说,redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口,比如:slaveof 192.168.10.10 6379,然后启动主从,主从 ...

  8. Jedis cluster集群初始化源码剖析

    Jedis cluster集群初始化源码剖析 环境 jar版本: spring-data-redis-1.8.4-RELEASE.jar.jedis-2.9.0.jar 测试环境: Redis 3.2 ...

  9. Redis Cluster 集群使用(3)

    简介 Redis3.0版本之前,可以通过Redis Sentinel(哨兵)来实现高可用(HA),从3.0版本之后,官方推出了Redis Cluster,它的主要用途是实现数据分片(Data Shar ...

随机推荐

  1. 【python代码】 最大流问题+最小花费问题+python(ortool库)实现

    目录 基本概念 图 邻接矩阵 最大流问题 python解决最大流问题 python解决最大流最小费用问题 基本概念 图 定义: 图G(V,E)是指一个二元组(V(G),E(G)),其中: V(G)={ ...

  2. Django之请求生命周期

    settings.py中间件执行 自定义中间件的配置: (1)任意新建一个py文件,导入模块from django.utils.deprecation import MiddlewareMixin ( ...

  3. ionic + asp.net core webapi + keycloak实现前后端用户认证和自动生成客户端代码

    概述 本文使用ionic/angular开发网页前台,asp.net core webapi开发restful service,使用keycloak保护前台页面和后台服务,并且利用open api自动 ...

  4. view组件的封装是否需要特有模型?

    必须需要. 现在接手的老项目,所有自定义组件全部使用的原始的全量数据,作为模型给view用来展示. 结果发现,基本数据的选择错误,需要选择另一个数据作为基本数据,这导致一个很麻烦的问题,需要改动全部的 ...

  5. 博客管理与文章发布系统-第三方模块及其用法Part1

    写个帖子记录一下自己写的第一个express完整项目. 所需第三方模块及其用法. 一.先把所需文件和准备工作写一下 写项目前的准备 1.创建所需文件夹 public 静态资源 model 数据库操作 ...

  6. 还不会K8S吗?先从kubeadm开始吧

    目录 1. 准备工作 1.1 机器准备 1.2 系统配置 1.2.1 主机名及域名解析 1.2.2 免密登录 1.2.3 配置yum源 1.2.4 安装必要依赖包 1.2.5 关闭防火墙.SELinu ...

  7. 解决2003 - 2003 - Can't connect to MySQL server on '127.0.0.1'(61 "Connection refused")

    1)右击数据库选择编辑连接2) 3)重新输入密码即可

  8. Spring 使用注解对事务控制详解与实例

    1.什么是事务 一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败. 事务的四个特征ACID: 原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分 ...

  9. 如何利用CSS选择器抓取京东网商品信息

    前几天小编分别利用Python正则表达式.BeautifulSoup.Xpath分别爬取了京东网商品信息,今天小编利用CSS选择器来为大家展示一下如何实现京东商品信息的精准匹配~~ CSS选择器 目前 ...

  10. Java IO(十七)FIleReader 和 FileWriter

    Java IO(十七)FIleReader 和 FileWriter 一.介绍 FIleReader 和 FileWriter 是读写字符文件的便利类,分别继承于 InputStreamReader ...