actor是State、Behavior、mailbox、children、supervisor strategy的容器java
一、高效併發Actor,異步、非阻塞、事件驅動的編程模型,輕量級線程
二、錯誤容忍fault-tolerant,let-it-crash, self-heal and never stop,supervisor hierarchies
三、可伸縮編程
重要的數據放在靠近root節點附近, 把風險分散到葉子節點
1.重啓是遞歸的
2.葉子節點將會頻繁重啓
3.避免重啓帶有重要狀態的actor架構
一、設置單獨的線程池處理阻塞的操做
二、使用future來阻塞,同時注意限制線程池的隊列長度,不要耗盡系統資源併發
一、即便經過restart也沒法啓動
二、被本身的supervisor關閉了
三、本身關閉
關閉的時候,會將剩餘的消息發送到系統的dead letter信箱
而後由系統郵箱接管,全部發送給它的消息都轉發到系統郵箱
當一個subordinate檢測到failure,它自動掛起本身以及他的子孫,而後給supervisor發送failure信號。app
supervisor能夠選擇異步
保持subordinate的已有狀態繼續post
清除subordinate狀態重啓spa
停掉subordinate線程
本身也選擇拋出異常本身failed掉
preRestart是個鉤子方法,默認是在重啓前終止掉它的子孫rest
/
最頂層的guardian, 使用的是SupervisorStrategy.stoppingStrategy,只要是碰到Exception,就會終止child。嚴格來說它不是一個actor,由於每一個actor都必須有supervisor。它是在bubble以外的,也叫作bubble-walker
/user
經過使用 system.actorOf()建立的actor都是user guardian的子孫
ActorSystem system = ActorSystem.create("HelloAkka"); ActorRef master = system.actorOf(Props.create(HelloAkka.class),"master");
這樣也意味着,一旦user guardian掛掉,全部actor將會被中止。
而後user建立的actor能夠經過getContext().actorOf去建立它的子孫。
final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class), "greeter");
/system
引入該guardian是爲了確保系統的一些使用actor實現的服務(好比日誌)也關閉掉。全部的Exception(除了ActorInitializationException和ActorKilledException)都會重啓,其餘throwables都是會再拋出來而後shut down整個actor system
/deadLetters
全部發到stopped或者不存在的actor的消息都會被路由到這個actor
/temp
系統建立的短暫actor
/remote
在這底下的全部actor都在遠程
一、suspend並遞歸suspend該child
二、調用舊actor的preRestart方法(默認是給children發送termination請求,而後調用postStop方法)
三、等待全部須要terminate的children中止,
四、建立新的actor
五、調用postRestart方法(默認調用preStart方法)
六、發送重啓請求給children
七、resume該actor
ActorContext.watch/unwatch(targetActorRef)
supervisor接受到Terminated信息以後,拋出DeatchPactException
OneForOneStrategy,只針對failed的節點極其子孫重啓
AllForOneStrategy,重啓該節點的全部兄弟,適用於一個節點與相鄰節點有複雜關係的,若是supervisor沒有處理Terminated信息,則會拋出DeathPactException,而後重啓它。stop在這種模式下不會自動terminate它的孩子
幾個特殊的actorRef
PromiseActorRef
DeadLetterActorRef
EmptyLocalActorRef
ActorSystem.actorSelection
// 建立一個actor system,名爲mySystem ActorSystem system = ActorSystem.create("mySystem"); // 建立一個名爲service的頂級actor system.actorOf(Props.create(LookupActor.class), "service"); // 使用絕對路徑獲取service ActorSelection service = system.actorSelection("akka://mySystem/user/service");
context.actorSelection
可使用..來訪問parent actor,便可以使用相對路徑
context.actorSelection("../brother") ! msg context.actorSelection("/user/serviceA") ! msg
actorOf僅僅用來建立新的actor
actorSelection僅僅用來查找已存在actor
actorFor被廢棄,用actorSelection替代
akka remote採用p2p的架構,基於
通訊是對稱的,A能夠通訊B,B也應該能夠通訊A
系統也是有收有發
HTTP或者是AKKA I/O適合採用client-server模式
actor send rule
send of the message to an actor happens before the receive of that message by the same actor.
actor subsequent processing rule
actor是按順序處理消息的,一個消息沒處理完,不會處理下一個。即actor的變量在內部對於處理中的消息都是可見的,無需volatile
at-most-once delivery(actor採起的方式)
消息被投遞0或1次,即消息可能被丟失。最高效。
at-least-once delivery(akka persistence採用)
消息至少投遞1次,即消息可能重複但不會丟失。須要重拾,同時保持state直到被接收
exactly-once delivery
消息只投遞一次,即既不重複也不丟失。最昂貴的,須要過濾重複的消息。
須要消息的ack
若是沒有在指定時間收到ack,須要重試機制
接收者須要有檢測/丟棄重複消息的機制
爲何不保證可靠性,akka具備分佈性,基於這種抽象,丟失是不可避免的。好比JVM的stackOverFlow、OOM,也好比mailbox滿了,或者接收的actor掛掉了等等。
A1給A2發送M1,M2,M3
A3給A2發送M4,M5,M6
那麼對於A2來講,M1到達因爲M2,M2到達因爲M3;M4到達因爲M5,M5到達因爲M6,但消息可能丟失,而M123與M456多是夾雜的。
上面僅僅對於用戶消息來講的,可是針對failure消息,不保證。好比C發送M給parent,而後發送failure消息F,那麼parent接受到的多是FM或者MF。
從resource目錄加載
final ActorSystem system = ActorSystem.create("CreationSystem",ConfigFactory.load("usoft9/remotecreation")); final ActorRef actor = system.actorOf(Props.create(CreationActor.class), "creationActor");
合併
Config firstConfig = ConfigFactory.load("complex1.conf"); Config secondConfig = ConfigFactory.load("complex2.conf"); //a.withFallback(b) a和b合併,若是有相同的key,以a爲準 Config finalConfig = firstConfig.withFallback(secondConfig); System.out.println(finalConfig.getString("complex-app.something")); //hello world System.out.println("simple-lib.foo"); //這個配置項是在complex2.conf中的