akka筆記

actor容器

actor是State、Behavior、mailbox、children、supervisor strategy的容器java

akka的特色

一、高效併發Actor,異步、非阻塞、事件驅動的編程模型,輕量級線程
二、錯誤容忍fault-tolerant,let-it-crash, self-heal and never stop,supervisor hierarchies
三、可伸縮編程

The Error Kernel pattern

重要的數據放在靠近root節點附近, 把風險分散到葉子節點
1.重啓是遞歸的
2.葉子節點將會頻繁重啓
3.避免重啓帶有重要狀態的actor架構

針對須要阻塞的場景:

一、設置單獨的線程池處理阻塞的操做
二、使用future來阻塞,同時注意限制線程池的隊列長度,不要耗盡系統資源併發

actor是何時終止?

一、即便經過restart也沒法啓動
二、被本身的supervisor關閉了
三、本身關閉
關閉的時候,會將剩餘的消息發送到系統的dead letter信箱
而後由系統郵箱接管,全部發送給它的消息都轉發到系統郵箱
當一個subordinate檢測到failure,它自動掛起本身以及他的子孫,而後給supervisor發送failure信號。app

處理failure的四種策略

supervisor能夠選擇異步

  • 保持subordinate的已有狀態繼續post

  • 清除subordinate狀態重啓spa

  • 停掉subordinate線程

  • 本身也選擇拋出異常本身failed掉
    preRestart是個鉤子方法,默認是在重啓前終止掉它的子孫rest

akka的頂層supervisor

clipboard.png

  • /
    最頂層的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都在遠程

重啓的過程(使用新actor替代舊actor)

一、suspend並遞歸suspend該child
二、調用舊actor的preRestart方法(默認是給children發送termination請求,而後調用postStop方法)
三、等待全部須要terminate的children中止,
四、建立新的actor
五、調用postRestart方法(默認調用preStart方法)
六、發送重啓請求給children
七、resume該actor

actor的監視

  • ActorContext.watch/unwatch(targetActorRef)

  • supervisor接受到Terminated信息以後,拋出DeatchPactException

  • OneForOneStrategy,只針對failed的節點極其子孫重啓

  • AllForOneStrategy,重啓該節點的全部兄弟,適用於一個節點與相鄰節點有複雜關係的,若是supervisor沒有處理Terminated信息,則會拋出DeathPactException,而後重啓它。stop在這種模式下不會自動terminate它的孩子

actor的引用、路徑及地址

clipboard.png

幾個特殊的actorRef

  • PromiseActorRef

  • DeadLetterActorRef

  • EmptyLocalActorRef

actor的查找

  • 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

clipboard.png

actorOf與actorSelection與actorFor

  • actorOf僅僅用來建立新的actor

  • actorSelection僅僅用來查找已存在actor

  • actorFor被廢棄,用actorSelection替代

Peer-to-Peer的架構

akka remote採用p2p的架構,基於

  • 通訊是對稱的,A能夠通訊B,B也應該能夠通訊A

  • 系統也是有收有發
    HTTP或者是AKKA I/O適合採用client-server模式

akka的內存模型

  • actor send rule

  1. 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-RETRY protocol

  • 須要消息的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。

config加載

  • 從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中的
相關文章
相關標籤/搜索