Akka-Cluster(1)- Cluster Singleton 單例節點

   關於cluster-singleton我在前面的博文已經介紹過,在這篇我想回顧一下它的做用和使用方法。首先,cluster-singleton就是集羣某個節點上的一個actor。任什麼時候間在集羣內保證只會有一個這種actor的實例。它能夠是在任何節點上,具體位置由akka-cluster系統的leader節點根據必定規則選定。當cluster-singleton所處的節點中止運做時leader會選擇另外一個節點,而後系統會將cluster-singleton遷移到新的節點上來保證集羣中必定有一個活着的cluster-singleton實例,不過值得注意的是遷移的actor會丟失它的內部狀態。在編程實踐中經常會須要保證一項程序功能只能由惟一的actor來運行的狀況,好比咱們須要保證某種運算的順序,這時在集羣環境裏就可使用cluster-singleton了。下面是cluster-singleton可能的一些使用場景:html

一、在集羣中的一個單點運算決策角色,或者是集羣各節點交互運算的協調角色node

二、集羣與外界軟件惟一的接口點編程

三、單一主角,多個從屬tcp

四、中央命名機制,或者中央路由邏輯ide

cluster-singleton的工做原理是:在集羣的全部節點上都部署一個能產生、啓動某singleton類型的ClusterSingletonManager,這樣能夠保證singleton能夠遷移到任何節點。集羣中的leader節點動態決定singleton的具體生存節點並指示該節點上的ClusterSingletonManager建立singleton實例。其它actor與singleton的交互是經過這個singleton類型的ClusterSingletonProxy進行的,這是cluster系統提供的一項與singleton交互的渠道服務,在須要接觸singleton時能夠建立ClusterSingletonProxy實例,而後把它看成目標發送操做消息,這樣就能夠保證cluster-singleton的位置透明特性了。測試

下面咱們就用個簡單的例子來示範cluster-singleton的使用看看它的惟一性和自動遷移特色:spa

構建一個簡單的actor:.net

class SingletonActor extends Actor with ActorLogging { import SingletonActor._ import akka.cluster._ override def receive: Receive = { case Greeting(msg) => log.info("*********got {} from {}********", msg, sender().path.address) case Relocate => log.info("*********I'll move from {}********", self.path.address) val cluster = Cluster(context.system) cluster.leave(cluster.selfAddress) case Die => log.info("*******I'm shutting down ... ********") self ! PoisonPill } }

把SingletonActor包嵌在ClusterSingletonManager裏:scala

bject SingletonActor {
  trait SingletonMsg {}
  case class Greeting(msg: String) extends SingletonMsg
  case object Relocate extends SingletonMsg
  case object Die extends SingletonMsg

 def props = Props(new SingletonActor) def createSingleton(port: Int) = { val config = ConfigFactory.parseString(s"akka.remote.netty.tcp.port=$port") .withFallback(ConfigFactory.parseString("akka.cluster.roles=[singleton]")) .withFallback(ConfigFactory.load()) val singletonSystem = ActorSystem("ClusterSingletonSystem",config) val singletonManager = singletonSystem.actorOf(ClusterSingletonManager.props( singletonProps = props, terminationMessage = Die, settings = ClusterSingletonManagerSettings(singletonSystem) .withRole(Some("singleton"))   //只部署在角色是singleton的節點上
 ), name = "singletonManager" ) } }

注意:singletonManager就是一個actor,因此是用actorOf(...)來構建的。如今這個singletonManager只能部署在singleton角色的節點上。netty

調用SingletonActor是經過ClusterSingletonProxy進行的:

object SingletonUser { import SingletonActor._ def sendToSingleton(msg: SingletonMsg) = { val config = ConfigFactory.parseString("akka.cluster.roles=[greeter]") .withFallback(ConfigFactory.load()) val system = ActorSystem("ClusterSingletonSystem",config) val singletonProxy = system.actorOf(ClusterSingletonProxy.props( "user/singletonManager", ClusterSingletonProxySettings(system).withRole(None) )) singletonProxy ! msg } }

withRole(None)表明singletonProxy能夠部署在任何節點上。下面是測試代碼:

import SingletonActor._ import SingletonUser._ object SingletonDemo extends App { createSingleton(2551)    //seednode
  createSingleton(2552) createSingleton(2553) createSingleton(2554) scala.io.StdIn.readLine() sendToSingleton(Greeting("hello from tiger")) scala.io.StdIn.readLine() sendToSingleton(Relocate) scala.io.StdIn.readLine() sendToSingleton(Greeting("hello from cat")) scala.io.StdIn.readLine() sendToSingleton(Die) scala.io.StdIn.readLine() }

檢驗一下輸出簡要:

[INFO] [10/25/2018 13:41:25.642] [ClusterSingletonSystem-akka.actor.default-dispatcher-3] [akka.tcp://ClusterSingletonSystem@127.0.0.1:51660/user/$a] Singleton identified at [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/user/singletonManager/singleton]
[INFO] [10/25/2018 13:41:25.654] [ClusterSingletonSystem-akka.actor.default-dispatcher-20] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/user/singletonManager/singleton] *********got hello from tiger from akka.tcp://ClusterSingletonSystem@127.0.0.1:51660********


[INFO] [10/25/2018 13:43:10.839] [ClusterSingletonSystem-akka.actor.default-dispatcher-3] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/user/singletonManager/singleton] *********I'll move from akka://ClusterSingletonSystem********
INFO] [10/25/2018 13:43:18.885] [ClusterSingletonSystem-akka.actor.default-dispatcher-2] [akka.tcp://ClusterSingletonSystem@127.0.0.1:51670/user/$a] Singleton identified at [akka.tcp://ClusterSingletonSystem@127.0.0.1:2552/user/singletonManager/singleton]
[INFO] [10/25/2018 13:43:18.886] [ClusterSingletonSystem-akka.actor.default-dispatcher-3] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2552/user/singletonManager/singleton] *********got hello from cat from akka.tcp://ClusterSingletonSystem@127.0.0.1:51670********

[INFO] [10/25/2018 13:43:18.156] [ClusterSingletonSystem-akka.actor.default-dispatcher-16] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/user/singletonManager/singleton] *******I'm shutting down ... ********
[INFO] [10/25/2018 13:43:18.177] [ClusterSingletonSystem-akka.remote.default-remote-dispatcher-18] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/system/remoting-terminator] Shutting down remote daemon.
[INFO] [10/25/2018 13:43:18.178] [ClusterSingletonSystem-akka.remote.default-remote-dispatcher-18] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/system/remoting-terminator] Remote daemon shut down; proceeding with flushing remote transports.
[INFO] [10/25/2018 13:43:18.215] [ClusterSingletonSystem-akka.remote.default-remote-dispatcher-14] [akka.tcp://ClusterSingletonSystem@127.0.0.1:2551/system/remoting-terminator] Remoting shut down.
相關文章
相關標籤/搜索