日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Akka系列---什么是Actor

發布時間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Akka系列---什么是Actor 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文已.Net語法為主,同時寫有Scala及Java實現代碼

?

嚴肅的說,演員是一個廣泛的概念,作為外行人我對Actor 模型的定義:

  Actor是一個系統中參與者的虛擬人物,Actor與Actor之間是可以相互溝通,所有的溝通都是通過Message

比如說一個呼叫中心,數以百萬計的客戶可能會呼叫一個1-800的號碼,并與許多可能的客戶服務代表進行對話

向這樣類型的交互可以使用演員建模

?

在Actor模型中,一切都是Actor,就想在面向對象編程(OOP)中一切都是"Object"一樣.在OOP中,你需要使用類和對象進行建模,在Akka中,你可以使用Actor和Message進行建模

以下是Akka中基本例子

using System;

using Akka.Actor;


namespace ActorsSendingMessages

{

? ? /// <summary>

? ? /// 在Akka.NET中Actor都繼承于UntypedActor。/// </summary>

? ? public class BasicActor : UntypedActor

? ? {

? ? ? ? protected override void PreStart()

? ? ? ? {


? ? ? ? }


? ? ? ? protected override void PreRestart(Exception reason, object message)

? ? ? ? {


? ? ? ? }


? ? ? ? protected override void OnReceive(object message)

? ? ? ? {

? ? ? ? ? ? //handle messages here

? ? ? ? }


? ? ? ? protected override void PostStop()

? ? ? ? {


? ? ? ? }


? ? ? ? protected override void PostRestart(Exception reason)

? ? ? ? {


? ? ? ? }

? ? }

}

什么是Message

可能已經注意到了BasicActor中定義的方法

.Net
protected override void OnReceive(object message) { //handle messages here

}

該OnReceive方法是Actor接收Message的地方,在Akka中,一個Message就是一個Object,Message可以是任意類型的實例

Actor通常只能處理特定類型的Message,如果Actor收到無法處理的Message,則不會觸發任何異常,一般只是將Message標記為"unhandled"
Message是不變的

什么是"不可變"的對象呢?

  不可變對象:是一個對象中的狀態(即該對象在內存中的內容)一旦被實例化就不能修改

類似于String類型(.net中 string)

  不可變的Message本質上是線程安全的.沒有線程可以修改不可變Message的內容,所以接收到原始Message的第二個線程不必擔心以前的線程有修改Message的可能

因此,在Akka中,所有消息都是不可變的,線程也是安全的,這也是為什么可以讓上千萬Akka的Actor同時處理消息的原因之一.正式不可變的Message消除了同步機制和其他不必要的代碼

Actor的行為

我們大概了解了Actor和Message,那這些如何用?

Actor通過Message進行通信

在OOP中,對象通過函數調用與其他對象進行通信.A類在B類上調用一個函數,并等待該函數返回,然后A類可以繼續其余工作.在Akka和Actor模型中,Actor之間通過Message進行通信

那有什么特別的呢?

  對于初學者來說,消息傳遞是異步的,發送Message的Actor可以在接收的Actor處理發件人的Message時繼續執行其他工作.所以Actor之間的互動,默認情況下都是異步的

還有另一個變化

  由于所有"函數調用"都被Message代替,即對象的不同實例,因此Actor可以存儲其函數調用的歷史記錄,甚至延遲處理一些函數調用

想象一下,如何使用一個Actor來構建像Microsoft Word中的“撤消”按鈕這樣的功能?默認情況下,你有一個Message代表每個人對文檔所做的更改.要撤消其中一個更改,只需要將消息從UndoActor的垃圾郵件中刪除,并將該更改推送回管理Word文檔的當前狀態的另一個Actor。在實踐中這是一個非常強大的概念。

Actor發送Message到地址,而不是直接發送給Actor

位置透明

  什么是位置透明,位置透明意味著無論在何時向Actor發送Message,都不需要知道他們在系統中的位置,可能這個Message覆蓋數百臺計算機,所以只需要知道Actor的地址.

就像給別人打電話一樣,你只需要知道電話號碼,其他的電信供應商就會幫你連通.

Actor的工作方式也是一樣,每個Actor都包含了以下部分地址

Protocol(協議):就像網絡上使用的Http和Https一樣,Akka支持多種傳輸協議用于進程間的通信.單進程Actor系統默認協議是akka://如果使用的遠程或者集群,則通常會使用akka.tcp://或者akka.udp://在節點之間進行通信

ActorSystem(Actor系統):在akka的每個ActorSystem實例必須在啟動時賦予一個名稱,該名稱可以由所有參與分布式的多個進程或者計算機共享ActorSystem.

Address(地址):如果不使用遠程處理,則ActorPath可以省略這一部分,這部分是用來傳達用于Actor系統之間的遠程通信的具體IP地址/域名和端口信息

Path(路徑):這是一個特定Actor在地址上的路徑,結構就像一個網站的Url,所有用戶定義的actor都是在/user/下

因此,要向Actor發送消息:

.Net

//local actor

var actorRef = MyActorSystem.Selection("/user/myActor");

actorRef.Tell("HI!");


//remote actor

var remoteActorRef = MyActorSystem.Selection("akka.tcp://MyActorSystem@localhost:1001/user/myActor");

remoteActorRef.Tell("HI!");

向遠程Actor發送Message就像本地Actor一樣,這就是位置透明的意思

發送給Actor地址的所有Message都是放置在屬于Actor的"郵箱"中

當向Actor發送Message時,該Message不會直接進入Actor的OnReceive方法.

Message被放置在按照FIFO(先進先出)順序排列的"郵箱"中,就像C#中Queue<T>(java中LinkedList)數據結構一樣.郵箱有一個非常簡單的工作,接收和掛起郵件,直到Actor準備好處理它們.

當Actor準備處理Message時,郵箱將把Message推送到Actor的OnReceive方法中,并運行Actor的消息處理方法.

Actor只能一次處理一個Message

Akka中保證參與者處理Message時,Actor的上下文和內部狀態都是線程安全的

之所以這樣的原因是:

  因為Message是不可變的,所以每個Message的內容本質上是線程安全的

  因為Message是串行處理的,所以更改一個actor的內部狀態和上下文都不需要跨多個線程進行同步

因此,一個Actor在它的OnReceive方法退出之前,都無法處理下一個Message.當處理完時,郵箱會將下一個可用的Message推送到OnReceive方法中

Actor可以擁有內部狀態

就像任何類一樣,Actor可以擁有自己的屬性和字段

當一個Actor重啟時,actor實例就像我們這個BasicActor類的一個實例一樣被銷毀并重新創建.

BasicActor創建新的一個實例,通過Props把構造函數的參數傳遞給新的實例

Actor有一個明確的生命周期

在Actor可以從郵箱中開始處理Message之前,必須由Actor系統進行實例化并運行其生命周期.

?

?

?Actor被創建并啟動,然后會花費大部分時間接收消息,如果不再需要Actor,可以終止或者停止Actor

  如果Actor以外崩潰(即拋出未處理的Exception),Actor的父級將從頭開始自動重啟Actor的生命周期,而不會丟失仍在Actor郵箱中的剩余的Message

結合之前的例子BasicActor中實現這個生命周期:

  Actor's constructor(構造函數):BasicActor沒有中并沒有聲明,而是使用了默認的構造函數,當然也可以使用任何帶參數的構造函數

  PreStart:這是在actor可以開始接收消息之運行,是放置初始化邏輯的好地方,在重啟時會被調用

  PreRestart:如果Actor意外失敗(即拋出未處理的Exception),Actor的父級會重啟Actor

  PostStop:一旦Actor停止并且不再接收消息,就會被調用,這里可以處理清理引用對象,PostStop在Actor重啟時不會調用,只有在人為關閉時才調用

  PostRestart:在PreRestart之后,PreStart之前被調用,這是可以處理崩潰錯誤和診斷報告

?

?每個Actor都有父級,有的有子級

 就像人一樣,Actor有父母,有的有祖父母,兄弟姐妹和孩子

 

這意味著每個Actor都必須由其他Actor創建,所以我們代碼:

.Net
var actorRef = MyActorSystem.ActorOf(Props.Create<BasicActor>(), "myActor"); actorRef.Tell("HI!");

?

在/user/根Actor下創建一個新的Actor,新的Actor的路徑就是/user/myActor

同樣,還可以在BasicActor中創建其他Actor

.Net
protected override void OnReceive(object message) { var childActor = Context.ActorOf(Props.Create<BasicChildActor>(), "child1");childActor.Tell("Hi!"); }

這樣childActor的路徑就是/user/myActor/child1/

父級監督子級

在關于Actor生命周期的部分中,提到了"Actor是由他們的父級進行重啟"的概念.這就類似于,每個家長都收到他們孩子發的特別的消息"求助,我要崩潰了".

每個父級都帶有默認的SuperviserStrategy對象(可以自定義).該對象決定了如何處理他們的子級Actor的失敗.有三種方式:

  Restart:重啟失敗的Actor,父級默認方式,除非子級在60秒內反復重啟

  Stop:永久停止失敗的Actor

  Escalate:將決定交給父級的父級處理

當發出一個Restart或者Stop 的Message,受影響的所有的子級包括自己都會重啟或者停止.當然,也可以重啟失敗的Actor的actor家族樹整個部分?

引薦:https://petabridge.com/blog/akkadotnet-what-is-an-actor/


原文地址:http://www.cnblogs.com/yangleiblog/p/6766197.html


.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Akka系列---什么是Actor的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。