澳门美高梅手机网站重装系统如何保存正版Win10和Office

 
 Akka-Cluster得以于同统物理机或同等组网连接的服务器上多建筑部署。用Akka开发同版本的分布式程序可以于另硬件环境被运行,这样我们虽可以确定以Akka分布式程序当做正式的编程方式了。

品牌机一般预装了正版Windows(单买要¥888),甚至还有正版Office(单买要¥749),价值不菲。但也预装了有“流氓”软件,导致开机后半龙无克动,所以自己重装很有必要。或者换固态硬盘了、中毒了,也待重装。这时候如何保持预装的正版Win10同Office2016休弃也?

 
 在上头两篇讨论里我们介绍了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将大半单JVM连接成起来,实现信息地址之透明化和统一化使用管理,集成一体化的信息让系统。最终目的是能够将一个大型程序分割成多只子程序,然后部署到特别多JVM上去实现程序的分布式并行运算。更要之凡:Cluster的构建过程和Actor编程没有牵涉,当Cluster把多独ActorSystem集合成一个合系统后,我们好就此当单一ActorSystem里编程的习惯方式编写分布式运算程序。由于当单一机器及即足以配备多独节点形成一个集群,我们开之分布式程序可以在单机或多机群上运行,不同之单是何许安排与安排集群环境。

查阅系统版本

右键点击开始菜单——系统,能看网版本。可以见到此电脑预装的凡64各类之“Windows
10 家庭中文版”,这吗是多数笔记本预装的本子。

2016-11-13.png

俺们第一来认识有关于Akka-Cluster的根底概念:

查看Win10序列号

本机的Win10之阵号颇易查下,按“Win”+
“R”,运行powershell,然后实施以下命令:

(Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey

win10 命令查看序列号

管方查到的排号记下来(用手机冲击下即可),比如“QWERT-ASDFG-ZXCVB-QWERT-ASDFG”。

Node:集群节点,也得说凡是象征一个单身的ActorSystem,用hostname:port来代表。一管物理机械上足构建多独集群节点Node,这时她有同样之hostname和不同的port,在不同机器及之Node则足以使不同的hostname和千篇一律的port。

查看Office版本

开辟控制面板——程序与效果,能顾预装的凡Office
365,而计算机及之贴纸明明写着是“Office
2016家中和和学生版”,没提到,激活后便变了。

控制面板-程序和机能 里面能看出预装的office

Cluster:由多只节点Node作为集群成员通过一致种集群组织协商形成集群的一个总体。

联网激活Office

当桌面右键新建一个Word文档,打开会相如下界面:

激活office

激活office-向某个帐户添加此密钥

把这秘密钥记下来为防万一。然后继续“联机兑换”。

一块兑换-1、登录

登录你的微软帐户,如果没的话,一定注册一个(打不起Gmail的事态下,微软邮箱是单正确的挑选)。

一同兑换-2、确认帐户设置

一道兑换-3、获取office

一起兑换-3、office已准备妥当

在网站上换了,回到Office软件就激活,输入才之微软帐户,然后要候很遥远,等Office自动安装完毕即可。

做到激活

激活office

选你的活

帐户已履新

关于word-激活后

这儿还刷新“程序及机能”,就见面发觉“Office 365”消失了,而起了“Office
2016家园与学生版”。通过者历程可以发现,Office序列号已经绑定到村办的微软账号里,所以重装系统也不见面丢掉了,刚才记的阵号才是因防万一,用非达了。

警告:
如果新市的计算机倒是一筹莫展激活Office,说明或者是别人退货的,或者公司把这Office序列号抄了用去售卖了,请尽早联系店家。买电脑一定要以:京东自营、苏宁自营、亚马逊自营、天猫品牌旗舰店、京东品牌旗舰店、苏宁品牌旗舰店,不要在电脑城或京东第三方/淘宝/天猫小店,否则出现这种软件纠纷很为难维权。

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

下载Win10制启动U盘,重装系统

既知道了预装的是64各项Win10家中中文版,到网上下载微软官方ISO镜像即可。微软官网(microsoft.com)免费提供Win10产充斥:

微软官网免费供win10下蛋充斥

兹计算机CPU都是64各类之了,建议系统为就此64各项的

Win10_1607_China_GGK_Chinese(Simplified)_x64.iso

系统ISO下载完毕,再下载rufus,然后插上U盘,用rufus做成启动U盘。PS:没有U盘的话,花几十块买一个纵推行了,当心名牌的恶劣产品,参考:《最缓慢的U盘排行榜,请不进》。

rufus

rufus选择ISO镜像

注意:选了ISO镜像下,上面的挑项会变,需要还选择成为“用于UEFI计算机的GPT分区方案”。

1.jpg

U盘做好以后,重开电脑,使用快捷键或者修改bios,从U盘启动,一步步重装即可。

开机按bios快捷键,选择从U盘启动

Win10安装界面

Win10装置界面,可以视令器0是新装的固态硬盘,而使器1里面是出厂带的体系

Win10安装界面,把总系统的分区全部剔除,把系统装于固态硬盘上

Win10安快得了

Win10装完成,进入了桌面

由主板里并了正版信息,大部分情景下非会见油然而生输入序列号的界面,重装完毕便见面发觉曾激活了。刚才记下的Win10队列号用非上了,只是以防万一。

Seed-Node:由同样还是多单集众多被之节点组成。一个节点在投入集群之前先向具有用户指定的Seed-Node发出联系信息,然后向首届对的Seed-Node发出参加集群请求。Seed-Node的严重性作用是啊申请加入集群的节点提供切实的关联地址,毕竟申请加入的节点需要一个切实可行的地点来发送申请加入消息,从这个上面来说:Seed-Node可以是集众多被任何已掌握地址的节点。

复正版Office

重装完系统,打开Office的安装网页setup.office.com,登录你的微软帐如泣如诉,别点“下一样步”,而是点“从Office.com/MyAccount安装”。

setup.office.com 点“安装”

我的Office帐户

默认是32员之,如果想诈64位的,就点“语言和安装选项——其他装置选项——Office的外版本”。这是联网下载安装,网速快的言辞不至1独钟头便吓了,如果嫌慢或者想留在下次重装时用,可以下载脱机安装程序(位置于:语言与设置选项——其他设置选项)。安装好,登录你的微软账号,即可激活。

言语与安装选项——点“其他装选项”

别装置选项——点“下充斥脱机安装程序”

微软当成够了,装软件还亟需牢记网址……还需要点很多潜藏的链接……

当您闹耐心看了这样丰富的篇章,估计为发觉了Windows这种单机操作系统实在太对用了,而手机及之iOS/Android互联网操作系统就是充分简单。个人建议:考虑于老人长辈打电脑时,如果急需是看录像电视剧、聊微信QQ、玩斗地主等小游戏,则不用请电脑了,买iPad即可(苹果官网9.7英寸最新款不至3000最先),简单好用,永不中毒。

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

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

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

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

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

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

Gossip-Convergence:集群统一状态。当Gossip交流覆盖了集群中负有节点,即具备节点都获得统一的集群状态,就直达集群统一状态Convergence。

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

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

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

 /**
   * 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))

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

/**
    * 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))

Akka-Cluster的集群节点状态转换可以看作事件于Akka的EventBus上披露:

  /**
   * 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

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

/**
   * 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
  }

用户可监听这些事件之发:

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

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

 /**
   * 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)
  }

脚我们即便因此个例来示范Akka-Cluster的运行过程:

率先要Akka-Cluster的dependency:build.sbt

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
  )
}

下一场是骨干的部署:cluster.conf

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"]
  }
}

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

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
  }

} 

下是EventListener使用测试代码,增加了Node加人集群后可能展开的首设置与退出集群后底事后清理:

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()


  }
}

我们当差不多个terminal上就此sbt来测试运行:

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

[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

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

[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

3、run “0” “2551”    
 //port=0澳门美高梅手机网站代表由系统自动选择端口

[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

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

[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

脚就此次示范的源代码:

resources/cluster.conf

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"]
  }
}

ClusterEventsDemo.scala

 

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()


  }
}

 

 

 

 

 

 

 

 

 

 

发表评论

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