好萊塢是一種超快的演員發動機,用於速度和低延遲應用。考慮遊戲服務器,廣告經紀人,交易引擎等...它可以在1秒內處理1000萬條消息。
Actor模型是用於構建高度並發和分佈式系統的計算模型。卡爾·休伊特(Carl Hewitt)在1973年引入了它,是一種以更可擴展和容忍性的方式處理複雜系統的方式。
在演員模型中,基本的構建塊是一個演員,有時被稱為好萊塢的接收器,這是一個獨立的計算單位,通過交換消息與其他參與者進行通信。每個演員都有自己的狀態和行為,只能通過發送消息與其他參與者進行交流。這種消息範圍的範式允許高度分散且容忍故障的系統,因為即使其他參與者失敗或不可用,演員也可以繼續獨立運作。
演員可以組織成等級制度,高級演員在監督和協調下層演員。這允許創建可以以優雅和可預測的方式處理故障和錯誤的複雜系統。
通過在您的應用程序中使用Actor模型,您可以構建高度可擴展且容易耐受的系統,這些系統可以處理大量並髮用戶和復雜的交互。
在演員失敗(緩衝機制)上保證消息傳遞
火與忘記或要求和響應消息,或兩者兼而有之
高性能DRPC作為運輸層
不反射的優化原始緩衝液
輕巧且高度可定制
集群支持編寫分佈式自我發現的演員
make bench
spawned 10 engines spawned 2000 actors per engine Send storm starting, will send for 10s using 20 workers Messages sent per second 3244217 .. Messages sent per second 3387478 Concurrent senders: 20 messages sent 35116641, messages received 35116641 - duration: 10s messages per second: 3511664 deadletters: 0
go get github.com/anthdm/hollywood/...
好萊塢需要Golang版本
1.21
我們建議您首先寫一些本地運行的示例。由於編譯器能夠找出所使用的類型,因此本地運行更簡單。遠程運行時,您需要為編譯器提供原始的定義。
讓我們瀏覽一個Hello World信息。完整的示例可在Hello World文件夾中找到。讓我們從主要開始:
引擎,err:= Actor.newEngine(Actor.newengineconfig())
這會創建一個新的引擎。引擎是好萊塢的核心。它負責產卵,發送消息和處理演員的生命週期。如果好萊塢未能創建引擎,它將返回錯誤。對於開發,您不應該將任何選項傳遞給發動機,以便您可以通過零。我們稍後再查看選項。
接下來,我們需要創建一個演員。這些接口必須實現之後,這些次數被稱為Receivers
。讓我們創建一個新演員,該演員將在收到消息時打印一條消息。
pid:= egine.spawn(newhelloer,“你好”)
這將導致引擎帶有ID“ Hello”的演員。演員將由提供的newHelloer
創建。 ID必須是唯一的。它將將指針返回到PID。 PID是過程標識符。這是演員的唯一標識符。大多數時候,您將使用PID向演員發送消息。在遠程系統中,您將使用ID發送消息,但是在本地系統上,您將主要使用PID。
讓我們看一下newHelloer
函數及其返回的演員。
type Helloer struct {} func newhelloer()actor.receiver {return&Helloer {} }
足夠簡單。 newHelloer
功能返回新演員。演員是實現Actor.receiver的結構。讓我們看看Receive
方法。
類型消息struct {} func(h *helloer)接收(ctx *actor.context){switch msg:= ctx.message()。演員啟動:fmt.println(“ Helloer at start”)案例演員:stopped :fmt.println(“ helloer已經停止”)案例*消息:fmt.println(“ hello world”,msg.data) } }
您可以看到我們定義了一個消息結構。這是我們稍後將發送給演員的信息。接收方法還處理其他一些消息。這些生命週期消息由引擎發送給演員,您將使用這些消息來初始化您的演員
引擎將Actor.Context傳遞到Receive
方法。此上下文包含消息,發件人的PID以及您可以使用的其他一些依賴關係。
現在,讓我們向演員發送一條消息。我們將發送一條message
,但是您可以發送所需的任何類型的消息。唯一的要求是演員必須能夠處理該消息。為了使消息能夠越過電線,它們必須是可序列化的。為了使Protobuf能夠序列化消息,必須是指針。本地消息可以是任何類型的。
最後,讓我們向演員發送一條消息。
Engine.Send(PID,“ Hello World!”)
這將向演員發送一條消息。好萊塢將把消息路由到正確的演員。然後,演員將向控制台打印一條消息。
示例文件夾是進一步學習和探索好萊塢的最佳場所。
當您產生演員時,您需要提供一個返回新演員的功能。由於演員是產卵的,您可以提供一些可調選項。
E.Spawn(newfoo,“ myactorname”)
有時,您需要將論點傳遞給演員構造函數。這可以通過使用閉合來完成。請求示例中有一個示例。讓我們看一下代碼。
默認構造函數將看起來像這樣:
func newnameresponder()actor.receiver {return&nameresponder {name:“ noname”} }
要構建一個名稱的新演員,您可以執行以下操作:
func newcustomnameresponder(name string)actor.producer {return func()actor.receiver {return&nameresponder {name} } }
然後,您可以使用以下代碼產生演員:
pid:= egine.spawn(newcustomnameresponder(“ Anthony”),“名稱響應器”)
E.Spawn(newfoo,“ myactorname”,Actor.withmaxrestarts(4),Actor.withinboxsize(1024 * 2),actor.withid(“ bar”), ) )
選項應該是非常自我解釋的。您可以設置最大重新啟動數量,該重新啟動數告訴引擎在恐慌的情況下應重新啟動給定演員多少次,這是收件箱的大小,這設定了收件箱可以在啟動之前可以保持的如何和未加工的消息限制阻止。
沒有狀態的演員可以作為功能產生,因為它快速而簡單。
e.SpawnFunc(func(c *actor.context){switch msg:= c.message()。 } },“ foo”)
演員可以通過網絡與遠程軟件包相互通信。這與本地演員相同,但“在電線上”。好萊塢支持Protobuf序列化。
remote.new()獲取一個收聽地址和一個遠程config struct。
您將使用以下代碼實例化新遙控器:
tlsconfig:= tlsconfig:&tls.config {證書:[] tls.certificate {cert}, } config:= remote.newconfig()。使用tls(tlsconfig)遠程:= remote.new(“ 0.0.0.0.0:2222”,config),ERGEN,err:= actor..newengine(actor.newengineconeconfig() )
查看遠程演員示例和聊天客戶端和服務器以獲取更多信息。
在生產系統中,事情最終會出錯。演員將崩潰,機器將失敗,消息將最終進入無生命隊列。您可以使用事件流構建可以以優雅且可預測的方式處理這些事件的軟件。
EventsTream是一個強大的抽象,可讓您在沒有依賴性的情況下構建靈活且可插入的系統。
將任何演員訂閱到系統事件的各種列表中
向所有訂戶廣播您的自定義活動
請注意,任何演員都沒有處理的事件將被丟棄。您應該有一個演員訂閱事件流以接收事件。最低限度,您需要處理DeadLetterEvent
。如果好萊塢未能向演員傳達信息,它將向事件流發送DeadLetterEvent
信息。
任何滿足actor.LogEvent
接口的事件都將記錄到默認記錄器,並具有嚴重性級別,消息和actor.LogEvent
log()
方法設置的事件的屬性。
actor.ActorInitializedEvent
,演員已被初始化,但沒有處理過其actor.Started message
actor.ActorStartedEvent
,演員已經開始
actor.ActorStoppedEvent
,演員已經停止
actor.DeadLetterEvent
,沒有傳達給演員的信息
actor.ActorRestartedEvent
,演員在崩潰/恐慌之後重新開始。
actor.RemoteUnreachableEvent
,將電線上的消息發送到無法到達的遙控器上。
cluster.MemberJoinEvent
,新成員加入集群
cluster.MemberLeaveEvent
,一個新成員離開了集群
cluster.ActivationEvent
,在群集上激活了一個新演員
cluster.DeactivationEvent
,演員在群集上停用
有一個EventsTream監視示例,向您展示瞭如何使用事件流。它具有兩個演員,一個是不穩定的,每秒都會崩潰。另一個參與者訂閱了事件流,並為不同事件(例如崩潰等)維護一些計數器。
該應用程序將運行幾秒鐘,而不穩定的演員將毒物毒藥。然後,它會用請求查詢監視器。隨著演員在引擎內部漂浮,這就是您與他們互動的方式。然後,MAIN將打印查詢結果,並將應用程序退出。
我們正在使用功能選項模式。所有功能選項均在Actor軟件包中,並使用“ EngineOpt”啟動其名稱。當前,唯一的選擇是提供遙控器。這是由
r:= remote.new(remote.config {listeraddr:addr})引擎,err:= actor.newengine(actor.enegineoptremote(r))
ADDR是帶有格式“主機:端口”的字符串。
您可以將自定義中間件添加到接收器中。這對於在actor.Started
和actor.Stopped
上存儲指標,保存和加載數據很有用。
有關如何實現自定義中間件的示例,請查看示例中的中間件文件夾
好萊塢有一些內置的伐木。它將使用log/slog
軟件包中的默認記錄器。您可以使用slog.SetDefaultLogger()
設置默認記錄器,將記錄器配置為您的喜好。這將使您可以自定義日誌級別,格式和輸出。有關更多信息,請參閱slog
軟件包”。
請注意,某些事件可能會記錄到默認記錄器,例如DeadLetterEvent
和ActorStartedEvent
因為這些事件滿足了actor.LogEvent
界面。有關更多信息,請參見上面的EventStream部分。
make test
加入我們的Discord社區,與2000多名成員進行問題和聊天良好。
該項目目前由以下組織/項目用於生產:
感官物聯網
好萊塢已獲得MIT許可證的許可。