Akka(10): 分布式运算:集群-Cluster

 

老二、女主角唐雨柔。说好的江南闺秀唐生小姐为?说好的兰心蕙质善解人意呢?说实在的,我竟发生头心疼娜扎,因为这个角色被它演绎下,黑她底人头改为倍数地加强。然而,有多少是剧作者的鼎也叫它背着了为?这里不分析娜扎高鼻深目的像,主要来分析一下性格。游戏雨柔从小就了解自己之遭际,知道自己在不了二十秋,虽然每个人都对准她说得等二十年后待姜世离净化了以后续命,但从唐海暨草谷,每个人的可怜神色都标明了没几只人真的确信能续上命,包括雨柔自己。因为时日无多,在大人之偏爱下,从小就妙手仁心的草谷学习医术,这三单标准,导致游戏雨柔,外表和温柔,个性坚定善良,她蛮少犹豫,想做的转业便定会失去举行。天资聪颖为身体贴,往往能事先一步感受及其他人的感受,说话恰到好处,不过分不放纵,她即使如相同枚和的江南水莲,不知不觉吃丁因舒适的感想。而剧版的雨柔呢,抱歉,这是一个性情极度不平静的青春型精神病的患儿。一会儿怀念表现和谐好,对大人的伤人救命的配置不听从。一会儿还要不顾小姜龙幽所举行的救民水火的所作所为好飞一边钓凯子玩乐去矣,善良的质地一湾脑就无了。一会儿怀念表现和谐善解人意,于是成了胖雨柔陪着姜云凡,一会儿又变成了冰冷的策反形象,跟师父师叔父亲说,这辈子从来没有吧协调生了,要随心所欲一把。我的天,她底即兴就是一边爱小姜爱得要死要活,一边以进而上官雅游山玩水嗑药吸毒?诸如此类的始末贯穿了电视剧的总。我异常惊讶,编剧的这种思维是千篇一律栽迎合迷茫的青春期学生的心理么?还是劝说大家,一言不合就离家出走,一言不合就钓凯子,一言不合就吸毒?

name := "cluster-states-demo"

version := "1.0"

scalaVersion := "2.11.8"

libraryDependencies ++= {
  val akkaVersion = "2.5.3"
  Seq(
    "com.typesafe.akka"       %%  "akka-actor"   % akkaVersion,
    "com.typesafe.akka"       %%  "akka-cluster"   % akkaVersion
  )
}

然而仙五文本中仍然发生好多独到之处,简单概括出以下几个点:

 

实则,一总统好的影视剧,无论是改编,还是原创,文本创作都是必不可少的如出一辙围,要惦记打出不错之创作,必然使精心打磨文本,没有成之捷径。而及时之电视剧,为了追求收益大、见效快,几乎以尽的年月、金钱都砸进了宣传被,而忽略了极根本之事物。当下盛行的IP电视剧,大都流为单纯追求故事热闹、情节离奇、演员脸蛋好看的偶像剧、仙侠剧的老路,单纯依靠IP来搜寻吸金的外壳,内里空洞无物。能静下心来做相同管电视剧的店堂越来越少,涸泽而渔随处可见。

import akka.actor._
import akka.cluster.ClusterEvent._
import akka.cluster._
import com.typesafe.config.ConfigFactory

class EventLisener extends Actor with ActorLogging {
  val cluster = Cluster(context.system)
  override def preStart(): Unit = {
    cluster.subscribe(self,initialStateMode = InitialStateAsEvents
    ,classOf[MemberEvent],classOf[UnreachableMember])  //订阅集群状态转换信息
    super.preStart()
  }

  override def postStop(): Unit = {
    cluster.unsubscribe(self)    //取消订阅
    super.postStop()
  }

  override def receive: Receive = {
    case MemberJoined(member) =>
      log.info("Member is Joining: {}", member.address)
    case MemberUp(member) =>
      log.info("Member is Up: {}", member.address)
    case MemberLeft(member) =>
      log.info("Member is Leaving: {}", member.address)
    case MemberExited(member) =>
      log.info("Member is Exiting: {}", member.address)
    case MemberRemoved(member, previousStatus) =>
      log.info(
        "Member is Removed: {} after {}",
        member.address, previousStatus)
    case UnreachableMember(member) =>
      log.info("Member detected as unreachable: {}", member)
      cluster.down(member.address)      //手工驱除,不用auto-down
    case _: MemberEvent => // ignore
  }

} 

次凡情真挚而多重。仙剑向来以情动人,刻画感情是仙剑的硬气。而仙五的情感除了爱情,更多了无数两样层面的真情实意,青石玉书之间相知相伴的师兄弟情,皇甫卓悲天悯人的泰斗情,唐海对雨柔、殷其雷对小姜的父女父子亲情,还有同伴之间的情谊,这是这些不同规模、不同角度的情交织在一块儿,构成了仙五的“情”。有些许人口于皇甫卓的那么句“别离失去的苦,我哉早已体会”而动,又闹微人深受凌音那句“世间父母最心痛的,便是老送黑发人。你打算于他留给小时间,让他好陪伴在好之女儿?”而动。世间本就是连爱情,为了爱情而自作主张的脱离现实的狗血剧情,只在吃琼瑶阿姨的小说里。

 

重设,雨柔一个黄花大姑娘,主动要求去山寨中住下,还同住就是停了漫漫,还不曾告诉家里,等及妻子来寻找才了解。然后后来还歇斯底里地犯病叛逆,说还向没呢投机生存了,敢问编剧,雨柔前面那么是为了唐海才去山寨的为?

resources/cluster.conf

《仙五云的凡》已经终结,对于中国人的末尾一统仙剑电视剧来说,赞少骂多,更夹杂在侵权手游等同样层层问题,对这部伴随着口水和骂声的电视剧,更多之丁感觉到连吐槽都无思量呕吐了。

 
 Akka-Cluster得以于同样总理物理机或同一组网连接的服务器上加建筑部署。用Akka开发同版本的分布式程序可以当旁硬件条件受到运作,这样咱们虽可以规定为Akka分布式程序当做规范的编程方式了。

相同凡人的脾气简单可充实,每个人都发友好的特征,寥寥几独镜头,一个整体的人选尽管跃然眼前,从口若是上看,落遢千山的姜云凡,玲珑可爱之小蛮,柔美脱俗的唐雨柔,风度翩翩的龙幽;从性情上看,小姜乐观阳光,雨柔坚定善良,龙幽精明重情,小蛮率真纯洁。仙五的主角团不异让外一个年份的著作,正是这几个热血青年支撑起了不到底完的仙五剧情。而博底龙套更是光彩照人,无论是天真可爱初具腹黑状的多少采薇,更富人情各具特色的蜀山七龙,还是父女情好的唐海,刚愈果决的欧阳慧,柔和温暖的海棠夫人,耿直忠心的血手,都是仙五吸引人之地方。

object ClusterEventsDemo {
  def main(args: Array[String]): Unit = {
    //重设port,seed-node-address
    val port =
      if (args.isEmpty) "0"
      else args(0)

    val addr =
      if (args.length < 2) "2551"
      else args(1)


    val seednodeSetting = "akka.cluster.seed-nodes = ["+
    "\"akka.tcp://clusterSystem@127.0.0.1:"+
      s"${addr}"+"\"]"


    val config = ConfigFactory.parseString(s"akka.remote.netty.tcp.port = ${port}")
      .withFallback(ConfigFactory.parseString(seednodeSetting))
      .withFallback(ConfigFactory.load("cluster.conf"))

    val clusterSystem = ActorSystem(name="clusterSystem",config=config)
    val eventListener = clusterSystem.actorOf(Props[EventLisener],"eventListener")

    val cluster = Cluster(clusterSystem)
    cluster.registerOnMemberRemoved(println("Leaving cluster. I should cleanup... "))
    cluster.registerOnMemberUp(println("Hookup to cluster. Do some setups ..."))
    println("actor system started!")
    scala.io.StdIn.readLine()

    clusterSystem.terminate()


  }
}

其余的,比如暗恋凌音的玉书,让人口莫名其妙。魔化的上官雅,让人莫名其妙。被人说夺权就夺权之欧阳英,让丁莫名其妙。无脑支持姜云凡的平供不应求,让人莫名其妙。无视门规存在的如出一辙丛蜀山学子,让人口莫名其妙。

集群节点Leave和Down实现方式如下: 

《云的凡》最为丁非的地方实际人设。因为太多,无法一一吐槽,只选几例,以犯证明。

Leader-Actions:当集群达Convergence后系活动选定一个Leader节点进行上述描述的节点状态转换操作。如果集群内生节点处Unreachable状态,无法达到集群Convergence,则无法满足任何节点状态转换请求。

抛除掉热门IP的过于消费,不考虑那些版权纠纷,仅仅对改编和改良的文书内核来,《云的凡》与任何的大网热门IP题材的电视剧来成千上万一律的问题,然而,即使宽容地来拘禁,《云之凡》也照样可以算是IP电视剧中之污辱,既未称,也不热门,轰轰烈烈地出生,静悄悄地走向死亡。

咱第一来认有有关Akka-Cluster的根基概念:

重新要,木翳将赢得七圣功力的小姜控制住。莫名其妙地就是忽然决定住了,按理说,能决定一个人数,要么就算是吃控制方的修为比控制方低,要么就是是于控制方的修为太死,濒临死亡,要么是什么异常能力。剧中并没外部木翳有这种力量,如果按照随便便就得决定,那他何必等这么长年累月,搞这么多从事,当年直接决定龙溟不就是实施了?后面一直控制姜世离,直接决定龙幽,直接决定蜀山七天,多方便。

 

主线剧情还是是按游戏来走,所以杀方向无换,然而小细节上曾经愈演愈烈,逻辑全无。仍然试举几单例证。

Leader:集众多中之某成员节点Node。由Akka自动在集群成员被选定,负责集群成员生命周期状态的现实性转换操作。

其三、压倒了小蛮的真•女二号凌音。默默地心疼我家高冷师妹五秒钟。

/**
    * Send command to issue state transition to LEAVING for the node specified by 'address'.
   * The member will go through the status changes [[MemberStatus]] `Leaving` (not published to
   * subscribers) followed by [[MemberStatus]] `Exiting` and finally [[MemberStatus]] `Removed`.
   *
   * Note that this command can be issued to any member in the cluster, not necessarily the
   * one that is leaving. The cluster extension, but not the actor system or JVM, of the
   * leaving member will be shutdown after the leader has changed status of the member to
   * Exiting. Thereafter the member will be removed from the cluster. Normally this is
   * handled automatically, but in case of network failures during this process it might
   * still be necessary to set the node’s status to Down in order to complete the removal.
   */
  def leave(address: Address): Unit =
    clusterCore ! ClusterUserAction.Leave(fillLocal(address))

  /**
   * Send command to DOWN the node specified by 'address'.
   *
   * When a member is considered by the failure detector to be unreachable the leader is not
   * allowed to perform its duties, such as changing status of new joining members to 'Up'.
   * The status of the unreachable member must be changed to 'Down', which can be done with
   * this method.
   */
  def down(address: Address): Unit =
    clusterCore ! ClusterUserAction.Down(fillLocal(address))

娱乐凌音是一个真•配角,与蜀山别样几各类长老一样,默默守护在蜀山、守护天下。在玩耍受,她是蜀山七龙中,唯一一个尚无斩断情缘的丁,她暗恋一供不应求。虽然作为蜀山长老,还动手暗恋这种事确实有接触未极端协调,但是细究,却具有其是的客观之处。因为凌音一直敬爱的姐,据说可能串通妖魔盗取蜀山神器,而且一去不回。虽然长老们并从未究肇事者妹妹凌音的事,反而暗自多方回护,令其未见面极其过伤心,但对它们的话,姐姐从此成为了不能言说的疼。为何背叛师门,为何抛弃自己,这些都改为了没有答案的来回,因此凌音从原本的温和贴心变成了后来底高冷御姐。而于蜀山达标之增长老中,能体会她这种失去别离的苦之总人口,只有已经的李逍遥,如今的同欠缺。太武师兄、草谷师姐就无须说了,青石、玉书那针对是当真修道之口,虽然会顺手体贴一下,但绝对不会见显现出来。铁笔也错过过,却看得通透。对于一个正到成年之女童来说,能加之安慰的,唯有一不足师兄,这种暗恋,不只是对爱情的想望,更多的是指向同病相怜的口之协助相伴。

ClusterEventsDemo.scala

《仙剑奇侠传五》是仙剑系列单机游戏中的第六管辖著作,也是新老交替、风格转换的一致总理作品。在付出进程被呢经历了起火、辞职等一样多样的波,导致这部著作本身便也丁非。无论是喜欢仙五的人数,还是无爱好仙五之人头,都不得不承认,仙五这部作品其实只能算半成品,前期的构建大,但后期的结束仓促,为了人要强行添加不客观剧情,逻辑混乱,都是部著作之题目。因此当仙五之后,又活了《仙剑奇侠传五前污染》,专门来啊五代填写坑。

[INFO] [06/26/2017 22:40:47.614] [clusterSystem-akka.actor.default-dispatcher-4] [akka.tcp://clusterSystem@127.0.0.1:2551/user/eventListener] Member is Leaving: akka.tcp://clusterSystem@127.0.0.1:53986
[INFO] [06/26/2017 22:40:48.032] [clusterSystem-akka.actor.default-dispatcher-15] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:2551] - Leader is moving node [akka.tcp://clusterSystem@127.0.0.1:53986] to [Exiting]
[INFO] [06/26/2017 22:40:48.032] [clusterSystem-akka.actor.default-dispatcher-21] [akka.tcp://clusterSystem@127.0.0.1:2551/user/eventListener] Member is Exiting: akka.tcp://clusterSystem@127.0.0.1:53986
[INFO] [06/26/2017 22:40:48.047] [clusterSystem-akka.actor.default-dispatcher-21] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:2551] - Exiting confirmed [akka.tcp://clusterSystem@127.0.0.1:53986]
[INFO] [06/26/2017 22:40:49.033] [clusterSystem-akka.actor.default-dispatcher-15] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:2551] - Leader is removing confirmed Exiting node [akka.tcp://clusterSystem@127.0.0.1:53986]
[INFO] [06/26/2017 22:40:49.033] [clusterSystem-akka.actor.default-dispatcher-21] [akka.tcp://clusterSystem@127.0.0.1:2551/user/eventListener] Member is Removed: akka.tcp://clusterSystem@127.0.0.1:53986 after Exiting

同等过多莫名其妙的人选,支撑由了一个通通没有逻辑,莫名其妙的剧情。

akka {
  actor {
    provider = "akka.cluster.ClusterActorRefProvider"
  }
  remote {
    log-remote-lifecycle-events = off
    netty.tcp {
      hostname = "127.0.0.1"
      port = 0
    }
  }
  cluster {
    seed-nodes = [
      "akka.tcp://clusterSystem@127.0.0.1:2551"]
  }
}

遵照,电视剧中放姜世离出血玉离开蜀山底始末。姜世离相当给反人类罪被判定关押蜀山,监禁终身。然而,小姜和龙幽为父子亲情为由,要求自由姜世离。——不考虑其他因素,单圈之剧情,这是丁话么?你杀人犯罪之前从没想了给人行凶的住家的父子亲情么?你犯案杀人后没有看罢为公拉的净天教弟子妻离子散的场景么?一句子父子亲情就能用一个倒人类罪的杀人犯放出来?犯人家属这么说,不怕被害人家属打死你们呢?蜀山增长老们居然就同意了,玉书还支持姜世离“宽容”的说教。这一定给监狱官员私纵凶犯,没理没有条件,因为杀人犯没将协调手下绑架的质撕票,就足以作为宽容,就加大了。呵呵,玄幻就得无曰法制讲传统?——姜世离是毫无疑问要是放开的,不然后面的情节无以为继,但是,能招来个再好的再发出说服力的说辞也?

 /**
   * The supplied thunk will be run, once, when current cluster member is `Up`.
   * Typically used together with configuration option `akka.cluster.min-nr-of-members`
   * to defer some action, such as starting actors, until the cluster has reached
   * a certain size.
   */
  def registerOnMemberUp[T](code: ⇒ T): Unit =
    registerOnMemberUp(new Runnable { def run() = code })

  /**
   * Java API: The supplied callback will be run, once, when current cluster member is `Up`.
   * Typically used together with configuration option `akka.cluster.min-nr-of-members`
   * to defer some action, such as starting actors, until the cluster has reached
   * a certain size.
   */
  def registerOnMemberUp(callback: Runnable): Unit =
    clusterDaemons ! InternalClusterAction.AddOnMemberUpListener(callback)

  /**
   * The supplied thunk will be run, once, when current cluster member is `Removed`.
   * If the cluster has already been shutdown the thunk will run on the caller thread immediately.
   * Typically used together `cluster.leave(cluster.selfAddress)` and then `system.terminate()`.
   */
  def registerOnMemberRemoved[T](code: ⇒ T): Unit =
    registerOnMemberRemoved(new Runnable { override def run(): Unit = code })

  /**
   * Java API: The supplied thunk will be run, once, when current cluster member is `Removed`.
   * If the cluster has already been shutdown the thunk will run on the caller thread immediately.
   * Typically used together `cluster.leave(cluster.selfAddress)` and then `system.terminate()`.
   */
  def registerOnMemberRemoved(callback: Runnable): Unit = {
    if (_isTerminated.get())
      callback.run()
    else
      clusterDaemons ! InternalClusterAction.AddOnMemberRemovedListener(callback)
  }

生矣仙五原先文件的独到之处和题材,在电视剧改编的经过遭到,应该考虑的是,如何在原作大的构建中找到平衡以及支点,将原作的缺憾补全,将原作的长强化。然而,非常惋惜,唐人的编剧完全无视原作,将《云之凡》改编成了扳平管辖借壳上市的“傻白甜”琼瑶狗血爱情偶像可以。

 

如此的逻辑缺陷数不胜数。没有一个克支持由剧情的人物形象,没有能够支持起人之逻辑情节,注定这部剧是烂剧中的烂斗机。

下面是一个集群状态转换事件的监听Actor:

任凭游戏作品可以,动漫创作可以,影视剧作品可以,讲好故事才是向,文本创作才是重头,只有通过严格的逻辑,完整的剧情,人物尽管地前进,足够强烈的抵触,才会将著作被包含在浓厚的内蕴,所体现的人头之盘算与意识、品格与人文精神,以及价值观、人生观、世界观等展示受观者。这恰恰是现之浮躁的时期所缺乏的“工匠精神”。

[INFO] [06/26/2017 21:25:46.743] [clusterSystem-akka.actor.default-dispatcher-3] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:2551] - Node [akka.tcp://clusterSystem@127.0.0.1:2551] is JOINING, roles []
[INFO] [06/26/2017 21:25:46.751] [clusterSystem-akka.actor.default-dispatcher-3] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:2551] - Leader is moving node [akka.tcp://clusterSystem@127.0.0.1:2551] to [Up]
[INFO] [06/26/2017 21:25:46.755] [clusterSystem-akka.actor.default-dispatcher-16] [akka.tcp://clusterSystem@127.0.0.1:2551/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:2551

当,热门IP登上大小荧屏,是急需阅历“伤筋动骨”的精益求精的。毕竟原作无论是漫画或打,小说还是网游,都具备和谐特殊的叙事方式,并不一定都称荧屏,比如《花千骨》,原作几百万字,比如哈利波特同漫威的影系列,都对准原作做了大气之推和修补,才见到我们面前。所以改编不是给地下的理,但无脑乱改就受人死反感了。

/**
   * Current snapshot state of the cluster. Sent to new subscriber.
   */
  final case class CurrentClusterState(
    members:       immutable.SortedSet[Member]  = immutable.SortedSet.empty,
    unreachable:   Set[Member]                  = Set.empty,
    seenBy:        Set[Address]                 = Set.empty,
    leader:        Option[Address]              = None,
    roleLeaderMap: Map[String, Option[Address]] = Map.empty) {

    /**
     * Java API: get current member list.
     */
    def getMembers: java.lang.Iterable[Member] = {
      import scala.collection.JavaConverters._
      members.asJava
    }

    /**
     * Java API: get current unreachable set.
     */
    def getUnreachable: java.util.Set[Member] =
      scala.collection.JavaConverters.setAsJavaSetConverter(unreachable).asJava

    /**
     * Java API: get current “seen-by” set.
     */
    def getSeenBy: java.util.Set[Address] =
      scala.collection.JavaConverters.setAsJavaSetConverter(seenBy).asJava

    /**
     * Java API: get address of current leader, or null if none
     */
    def getLeader: Address = leader orNull

    /**
     * All node roles in the cluster
     */
    def allRoles: Set[String] = roleLeaderMap.keySet

    /**
     * Java API: All node roles in the cluster
     */
    def getAllRoles: java.util.Set[String] =
      scala.collection.JavaConverters.setAsJavaSetConverter(allRoles).asJava

    /**
     * get address of current leader, if any, within the role set
     */
    def roleLeader(role: String): Option[Address] = roleLeaderMap.getOrElse(role, None)

    /**
     * Java API: get address of current leader within the role set,
     * or null if no node with that role
     */
    def getRoleLeader(role: String): Address = roleLeaderMap.get(role).flatten.orNull
  }

其三是阴谋刻画的浓。好人不是无脑的好,坏人呢非是特别透腔的雅,每个人犹发生谈得来之身份、立场,没有无缘无故的爱,也从未无缘无故的怨恨。我于刷游戏一到家目的时,很不便看起各个一个细节之状,是以结尾青石解析整个事件经过的上才赫然。二周目,认真地品读每一个情节,认真地朗诵每一个NPC的对话,这才察觉,哪起那么多之偶合,每一个恰好的末尾,都是阴谋的企图。虽然仙五末还是有成千上万逻辑混乱的地方,但这种阴谋的写展开,仍然是仙五的一个独到之处。(如果构成五前来拘禁,就更完整动人)

Membership-State:
集群状态,是一个集群内享有节点共享的数据结构,用于存放群内所有节点状态。集群状态是同样种CRDT数据结构,提供安全方便的多寡统一操作,方便逐步累加型数据统一更新。

再度不用取那些要稍加认真一点都得以避的错误——比如,片尾演员表中,皇甫卓被错印成了“黄浦卓”然而剧里仍然为着“皇甫门主”。比如,凌音还无投入到蜀山七上中的当儿,姜世离就等于正“蜀山七龙到来还发打算”。比如,青石说“过来为我看吧。”

Seed-Node:由同还是多单聚众众多被之节点组成。一个节点在进入集群之前先往具有用户指定的Seed-Node发出联系信息,然后向第一对的Seed-Node发出参加集群请求。Seed-Node的要作用是啊申请加入集群的节点提供切实的联系地址,毕竟申请加入的节点需要一个具体的地址来发送申请加入消息,从这上面来说:Seed-Node可以是集结众多被其他已解地址的节点。

万一于电视剧中,差点变成了小三儿的凌音,是一个奇葩之在。被木翳的阴谋蒙蔽了双眼,以为是最好武师兄杀了凌波,毫无置疑,莫名琼瑶,这点智商就吃人分外怀疑它们是不是负裙带关系才当上的蜀山七龙。被备胎玉书喜欢着,喜欢在龙幽,明知道对方是勿怀好意,仍然做出那么难看的从业,跟她长老的地位、音圣的名号一点儿也非适合。龙幽那句“看来这蜀山之上,还真是人人心中还有一样卖情”实在叫人口齿冷,如果想构建一个载爱意的门派,麻烦把修道两个字去丢。一浩大道士从一直到稍微个个爱来善去之不肉麻嘛?在我看来,同门的关心、知己的交情,永远比所谓的“爱情”更打动人。当然,也不绝于耳是蜀山,狂风寨、四雅世家也都是无辜受害者,就从未有过一个尚无子女情爱的绝望地方。也受自己深地多疑,唐人的编剧就是充满脑子都是善,爱得尤其狗血越来越好,爱之逾琼瑶越抓住人口?(同人YY的未到底,这是粉丝的权)这一点正是许多逛戏粉最为厌恶之地方。

cluster.subscribe(self, initialStateMode = InitialStateAsEvents,
  classOf[MemberEvent], classOf[UnreachableMember])

同样、最终之BOSS。虽然保留了原作的魔翳(即电视剧被的木翳和枯木,这是与一个人口)的身价,但与原作的丰赡理由了相反,魔翳由为国为民鞠躬尽瘁的形象,变成了一个能动挑起人魔两界争端的纯的阴谋家。这就算为人口好不便接受了,毕竟没有无缘无故的怨恨,原作的魔翳的抉择与各个一样步阴谋都是同龙溟共同商议的结果,他只是老己所能够的在实施,他从没背叛夜叉,更没有背叛龙溟龙幽,甚至为拿龙溟的魔元带离而深受毒火伤了宿体。而电视剧版的木翳为了唤起事端,主动关闭了幽冥界的基石,置自己的臣民死活要不顾,更为了实现和谐之目的而大了前人君主龙溟。这样一个“坏”得这么脸谱化的坏东西,还算连童话故事都无太能找到了。

Gossip-Convergence:集群统一状态。当Gossip交流覆盖了集群中保有节点,即具有节点都赢得统一之集群状态,就上集群统一状态Convergence。

Joining->Up,Leaving->Exiting,Exiting->Removed,Unreachable->Up,Unreachable->Down,Down->Removed

 

akka {
  actor {
    provider = "cluster"
  }
  remote {
    log-remote-lifecycle-events = off
    netty.tcp {
      hostname = "127.0.0.1"
      port = 2551
    }
  }
  cluster {
    seed-nodes = [
      "akka.tcp://clusterSystem@127.0.0.1:2551"]
  }
}

脚我们就用个例来示范Akka-Cluster的运作过程:

Failure-Detector
fd:所有节点都具备心跳信号交流功能。集众多被有节点可能让多个节点用heartbeat检测在线是否Reachable/Unreachable。如果凑众多被其他一个节点处Unreachable状态则通集群无法直达交Convergence状态。

此外,我们尚足以用callback方式于状态转换前后调用一些运算来开展准备处理及后拍卖:

 

下面是EventListener使用测试代码,增加了Node加人集群后或者进行的首设置与退集群后的后清理:

 

import akka.actor._
import akka.cluster.ClusterEvent._
import akka.cluster._
import com.typesafe.config.ConfigFactory

class EventLisener extends Actor with ActorLogging {
  val cluster = Cluster(context.system)
  override def preStart(): Unit = {
    cluster.subscribe(self,initialStateMode = InitialStateAsEvents
    ,classOf[MemberEvent],classOf[UnreachableMember])  //订阅集群状态转换信息
    super.preStart()
  }

  override def postStop(): Unit = {
    cluster.unsubscribe(self)    //取消订阅
    super.postStop()
  }

  override def receive: Receive = {
    case MemberJoined(member) =>
      log.info("Member is Joining: {}", member.address)
    case MemberUp(member) =>
      log.info("Member is Up: {}", member.address)
    case MemberLeft(member) =>
      log.info("Member is Leaving: {}", member.address)
    case MemberExited(member) =>
      log.info("Member is Exiting: {}", member.address)
    case MemberRemoved(member, previousStatus) =>
      log.info(
        "Member is Removed: {} after {}",
        member.address, previousStatus)
    case UnreachableMember(member) =>
      log.info("Member detected as unreachable: {}", member)
      cluster.down(member.address)      //手工驱除,不用auto-down
    case _: MemberEvent => // ignore
  }

}

object ClusterEventsDemo {
  def main(args: Array[String]): Unit = {
    //重设port,seed-node-address
    val port =
      if (args.isEmpty) "0"
      else args(0)

    val addr =
      if (args.length < 2) "2551"
      else args(1)


    val seednodeSetting = "akka.cluster.seed-nodes = ["+
    "\"akka.tcp://clusterSystem@127.0.0.1:"+
      s"${addr}"+"\"]"


    val config = ConfigFactory.parseString(s"akka.remote.netty.tcp.port = ${port}")
      .withFallback(ConfigFactory.parseString(seednodeSetting))
      .withFallback(ConfigFactory.load("cluster.conf"))

    val clusterSystem = ActorSystem(name="clusterSystem",config=config)
    val eventListener = clusterSystem.actorOf(Props[EventLisener],"eventListener")

    val cluster = Cluster(clusterSystem)
    cluster.registerOnMemberRemoved(println("Leaving cluster. I should cleanup... "))
    cluster.registerOnMemberUp(println("Hookup to cluster. Do some setups ..."))
    println("actor system started!")
    scala.io.StdIn.readLine()

    clusterSystem.terminate()


  }
}

Node:集群节点,也得以说凡是表示一个独立的ActorSystem,用hostname:port来代表。一统物理机械上可构建多单集群节点Node,这时她有着一样的hostname和不同的port,在不同机器及之Node则可用不同的hostname和均等的port。

[INFO] [06/26/2017 21:26:57.467] [run-main-1e] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:52459] - Started up successfully
actor system started!
[INFO] [06/26/2017 21:26:57.735] [clusterSystem-akka.actor.default-dispatcher-4] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:52459] - Welcome from [akka.tcp://clusterSystem@127.0.0.1:2551]
[INFO] [06/26/2017 21:26:57.751] [clusterSystem-akka.actor.default-dispatcher-3] [akka.tcp://clusterSystem@127.0.0.1:52459/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:2551
[INFO] [06/26/2017 21:26:57.752] [clusterSystem-akka.actor.default-dispatcher-3] [akka.tcp://clusterSystem@127.0.0.1:52459/user/eventListener] Member is Joining: akka.tcp://clusterSystem@127.0.0.1:52459
[INFO] [06/26/2017 21:26:57.809] [clusterSystem-akka.actor.default-dispatcher-16] [akka.tcp://clusterSystem@127.0.0.1:52459/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:52459
 /**
   * Try to join this cluster node with the node specified by 'address'.
   * A 'Join(selfAddress)' command is sent to the node to join.
   *
   * An actor system can only join a cluster once. Additional attempts will be ignored.
   * When it has successfully joined it must be restarted to be able to join another
   * cluster or to join the same cluster again.
   *
   * The name of the [[akka.actor.ActorSystem]] must be the same for all members of a
   * cluster.
   */
  def join(address: Address): Unit =
    clusterCore ! ClusterUserAction.JoinTo(fillLocal(address))

  /**
   * Join the specified seed nodes without defining them in config.
   * Especially useful from tests when Addresses are unknown before startup time.
   *
   * An actor system can only join a cluster once. Additional attempts will be ignored.
   * When it has successfully joined it must be restarted to be able to join another
   * cluster or to join the same cluster again.
   */
  def joinSeedNodes(seedNodes: immutable.Seq[Address]): Unit =
    clusterCore ! InternalClusterAction.JoinSeedNodes(seedNodes.toVector.map(fillLocal))

Akka-Cluster的集群节点状态转换可以当作事件于Akka的EventBus上宣告:

咱在差不多只terminal上之所以sbt来测试运行:

脚就是此次示范的源代码:

简简单单的话Akka-Cluster将大半只JVM连接成起来,实现信息地址的透明化和统一化使用管理,集成一体化的音信使得系统。最终目的是能将一个巨型程序分割成多独子程序,然后部署及不行多JVM上去实现程序的分布式并行运算。更要紧的凡:Cluster的构建过程与Actor编程没有关,当Cluster把多独ActorSystem集合成一个联结系统后,我们可以就此在单一ActorSystem里编程的习惯方式编写分布式运算程序。由于当单纯机器上便好配备多独节点形成一个集群,我们开之分布式程序可以在单机或多机群上运行,不同之光是怎么安排及布置集群环境。

1、run “2551” “2551”  
//这是个seed-node

Membership:集群成员组织是由此Gossip沟通协商将多只节点组织起形成的一个集群整体。

Cluster:由多个节点Node作为集群成员通过同样栽集群组织协议形成集群的一个圆。

在terminal2运算cluster.leave(cluster.selfAddress):

第一需要Akka-Cluster的dependency:build.sbt

此外,Akka-Cluster通过交流中心跳信号(heart-beat
signal)方式得以监测任何节点是否处于无法联络Unreachable状态。

[INFO] [06/26/2017 21:28:22.577] [run-main-1] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:52467] - Started up successfully
actor system started!
[INFO] [06/26/2017 21:28:22.736] [clusterSystem-akka.actor.default-dispatcher-2] [akka.cluster.Cluster(akka://clusterSystem)] Cluster Node [akka.tcp://clusterSystem@127.0.0.1:52467] - Welcome from [akka.tcp://clusterSystem@127.0.0.1:2551]
[INFO] [06/26/2017 21:28:22.747] [clusterSystem-akka.actor.default-dispatcher-16] [akka.tcp://clusterSystem@127.0.0.1:52467/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:2551
[INFO] [06/26/2017 21:28:22.749] [clusterSystem-akka.actor.default-dispatcher-16] [akka.tcp://clusterSystem@127.0.0.1:52467/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:52459
[INFO] [06/26/2017 21:28:22.749] [clusterSystem-akka.actor.default-dispatcher-16] [akka.tcp://clusterSystem@127.0.0.1:52467/user/eventListener] Member is Joining: akka.tcp://clusterSystem@127.0.0.1:52467
[INFO] [06/26/2017 21:28:24.611] [clusterSystem-akka.actor.default-dispatcher-22] [akka.tcp://clusterSystem@127.0.0.1:52467/user/eventListener] Member is Up: akka.tcp://clusterSystem@127.0.0.1:52467

3、run “0” “2551”    
 //port=0代表由系统自动选择端口

 

  /**
   * Marker interface for membership events.
   * Published when the state change is first seen on a node.
   * The state change was performed by the leader when there was
   * convergence on the leader node, i.e. all members had seen previous
   * state.
   */
  sealed trait MemberEvent extends ClusterDomainEvent {
    def member: Member
  }

  /**
   * Member status changed to Joining.
   */
  final case class MemberJoined(member: Member) extends MemberEvent {
    if (member.status != Joining) throw new IllegalArgumentException("Expected Joining status, got: " + member)
  }

  /**
   * Member status changed to WeaklyUp.
   * A joining member can be moved to `WeaklyUp` if convergence
   * cannot be reached, i.e. there are unreachable nodes.
   * It will be moved to `Up` when convergence is reached.
   */
  final case class MemberWeaklyUp(member: Member) extends MemberEvent {
    if (member.status != WeaklyUp) throw new IllegalArgumentException("Expected WeaklyUp status, got: " + member)
  }

  /**
   * Member status changed to Up.
   */
  final case class MemberUp(member: Member) extends MemberEvent {
    if (member.status != Up) throw new IllegalArgumentException("Expected Up status, got: " + member)
  }

  /**
   * Member status changed to Leaving.
   */
  final case class MemberLeft(member: Member) extends MemberEvent {
    if (member.status != Leaving) throw new IllegalArgumentException("Expected Leaving status, got: " + member)
  }

  /**
   * Member status changed to `MemberStatus.Exiting` and will be removed
   * when all members have seen the `Exiting` status.
   */
  final case class MemberExited(member: Member) extends MemberEvent {
    if (member.status != Exiting) throw new IllegalArgumentException("Expected Exiting status, got: " + member)
  }

  /**
   * Member completely removed from the cluster.
   * When `previousStatus` is `MemberStatus.Down` the node was removed
   * after being detected as unreachable and downed.
   * When `previousStatus` is `MemberStatus.Exiting` the node was removed
   * after graceful leaving and exiting.
   */
  final case class MemberRemoved(member: Member, previousStatus: MemberStatus) extends MemberEvent {
    if (member.status != Removed) throw new IllegalArgumentException("Expected Removed status, got: " + member)
  }
  /**
   * Marker interface to facilitate subscription of
   * both [[UnreachableMember]] and [[ReachableMember]].
   */
  sealed trait ReachabilityEvent extends ClusterDomainEvent {
    def member: Member
  }

  /**
   * A member is considered as unreachable by the failure detector.
   */
  final case class UnreachableMember(member: Member) extends ReachabilityEvent

  /**
   * A member is considered as reachable by the failure detector
   * after having been unreachable.
   * @see [[UnreachableMember]]
   */
  final case class ReachableMember(member: Member) extends ReachabilityEvent

Gossip-Protocal:是Node之间的交流协议。集群内的节点分邻里相互通过Gossip交流更新集群状态数据,逐步扩散交流覆盖全集群拥有节点并摇身一变整体的汇合集群状态数据。

2、run “0” “2551”    
 //port=0代表由网活动选择端口

然后是骨干的布局:cluster.conf

Node-Lifecycle-State:一个节点的生命周期里连以下几只状态转换:

 

 
 于上头两篇讨论里我们介绍了Akka-Remoting。Akka-Remoting其实是均等种植ActorSystem之间Actor对Actor点对碰之关联协商。通过Akka-Remoting来兑现一个ActorSystem中的一个Actor与其余一个Actorsystem中之别一个Actor之间的维系。在Remoting功能后,Akka又提高了集群Cluster功能。Akka-Cluster是根据Akka-Remoting之上的新一代分布式运算环境,所以Remoting已经成为了Akka-Cluster的其中支持作用,在生育环境遭受的分布式运算应该尽可能采用Akka-Cluster。当然,人们依然可以当读书及测试环境中应用Akka-Remoting来了解Akka的分布式运算机制与规律。Remoting和Cluster的赫分别有即是真的兑现了Actor的职务透明化。让编程人员可以再自在自然之落实分布式编程。当然,更主要的凡相对Akka-Remoting而言,Akka-Cluster提供了身更安全、更迅捷的分布式运算环境。

用户可监听这些事件的来:

 

当Akka-Cluster中一个节点加入集群是机关的,只要以配置文件里安装一个Seed-Node清单,否则便必以Actor程序里之所以Cluster.join或Cluster.joinSeedNodes方法加人:

集群的脚下状态值是存放于底下CurrentClusterState结构里的: 

发表评论

电子邮件地址不会被公开。 必填项已用*标注