Akka之在IoT系统中使用Actor(一)
(一)IoT系統(tǒng)介紹
通過了解Actor的層次結(jié)構(gòu)和行為,剩下的問題是如何將IoT系統(tǒng)的頂層組件映射到actor。將代表設備和儀表板的Actor放在頂層可能很誘人。相反,我們建議創(chuàng)建一個代表整個應用程序的顯式組件。換句話說,我們將在物聯(lián)網(wǎng)系統(tǒng)中擁有一名頂級Actor。創(chuàng)建和管理設備和儀表板的組件將是此Actor的子組件。這允許我們將IoT系統(tǒng)用Actor樹來表示:
?(二)IoT系統(tǒng)的頂層
?我們可以使用幾行簡單的代碼來定義第一個actor,即IotSupervisor。
import akka.actor.AbstractActor; import akka.actor.Props; import akka.event.Logging; import akka.event.LoggingAdapter;public class IotSupervisor extends AbstractActor {private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);public static Props props() {return Props.create(IotSupervisor.class, IotSupervisor::new);}@Overridepublic void preStart() {log.info("IoT Application started");}@Overridepublic void postStop() {log.info("IoT Application stopped");}// No need to handle any messages@Overridepublic Receive createReceive() {return receiveBuilder().build();} } import java.io.IOException;import akka.actor.ActorSystem; import akka.actor.ActorRef;public class IotMain {public static void main(String[] args) throws IOException {ActorSystem system = ActorSystem.create("iot-system");try {// Create top level supervisorActorRef supervisor = system.actorOf(IotSupervisor.props(), "iot-supervisor");System.out.println("Press ENTER to exit the system");System.in.read();} finally {system.terminate();}} }(三)設備actor?
如果我們使用對象,我們通常會將API設計為接口,這是由實際實現(xiàn)填充的抽象方法的集合。在Actor的世界中,協(xié)議取代了接口。雖然不可能在編程語言中形式化通用協(xié)議,但我們可以編寫它們最基本的元素,即消息。因此,我們將首先確定要發(fā)送給設備Actor的消息。
通常,消息屬于類別或模式。通過識別這些模式,您會發(fā)現(xiàn)在它們之間進行選擇并實現(xiàn)它們變得更加容易。
設備actor的任務很簡單:
??? ?收集溫度測量值
??? ?當被問到時,報告最后測量的溫度
但是,設備可能在啟動時沒有立即進行溫度測量。因此,我們需要考慮溫度不存在的情況。這也允許我們在沒有寫入部分的情況下測試actor的查詢部分,因為設備actor可以報告空結(jié)果。
用于從設備actor獲得當前溫度的協(xié)議是簡單的。
1.?? ?等待當前溫度的請求。
2.?? ?響應請求并回復:包含當前溫度或者表示溫度尚不可用。
我們需要兩條消息,一條用于請求,另一條用于回復。
這兩條消息似乎涵蓋了所需的功能。但是,我們選擇的方法必須考慮應用程序的分布式特性。雖然與本地JVM上的actor進行通信的基本機制與遠程actor相同,但我們需要牢記以下幾點:
??? ?本地和遠程消息之間的傳遞延遲將存在可觀察到的差異,因為網(wǎng)絡鏈路帶寬和消息大小等因素也會發(fā)揮作用。
??? ?可靠性是一個問題,因為遠程消息發(fā)送涉及更多步驟,這意味著更多可能出錯。
??? ?本地發(fā)送將傳遞對同一JVM內(nèi)的消息的引用,而不會對發(fā)送的基礎對象進行任何限制,而遠程傳輸將對消息大小設置限制。
此外,雖然在同一個JVM內(nèi)部發(fā)送更可靠,但如果一個Actor在處理消息時由于程序員錯誤而失敗,其效果就像遠程主機請求因處理消息時遠程主機崩潰而失敗一樣。即使在這兩種情況下,服務都會在一段時間后恢復(Actor由其supervisor重新啟動,host由運營商或監(jiān)控系統(tǒng)重新啟動)在崩潰期間各個請求都會丟失。因此,寫下你的Actor,使每條消息都可能丟失,這是安全、悲觀的賭注。
但是為了進一步理解協(xié)議的靈活性需求,將有助于考慮Akka消息排序和消息傳遞保證。Akka為消息發(fā)送提供以下行為:
??? ?最多一次傳遞,即無保證傳遞。
??? ?每個發(fā)送者、接收者對維護消息排序。?
一、消息傳遞
消息傳遞子系統(tǒng)提供的傳遞語義通常分為以下幾類:
??? ?最多一次發(fā)送 - 每條消息一次或零次發(fā)送 ; 在更多的因果關(guān)系中,這意味著消息可能會丟失,但永遠不會重復。
??? ?至少一次傳遞 - 可能會多次嘗試傳遞每條消息,直到至少一次成功; 這意味著消息可以重復,但永遠不會丟失。
??? ?完全一次發(fā)送 - 每條消息只發(fā)送一次給收件人; 消息既不會丟失也不會重復。
第一種方式是最便宜的,并且性能最高。它具有最少的實現(xiàn)開銷,因為它可以以一種即發(fā)即忘的方式完成,而不會將狀態(tài)保持在發(fā)送端或傳輸機制中。第二種方式,需要至少一次重試以抵消運輸損失。這增加了將狀態(tài)保持在發(fā)送端并在接收端具有確認機制的開銷。第三種方式完全一次交付是最昂貴的,并且導致最差的性能:除了至少一次交付所增加的開銷之外,它還要求將狀態(tài)保持在接收狀態(tài)以便過濾掉重復的交付。
在Actor系統(tǒng)中,我們需要保證一個確切的含義 - 系統(tǒng)在何時將發(fā)送視為已完成:
1.?? ?當消息在網(wǎng)絡上發(fā)送出去?
2.?? ?當目標actor的主持人收到消息時?
3.?? ?當消息被放入目標actor的郵箱時?
4.?? ?當消息目標actor開始處理消息時?
5.?? ?目標actor何時成功處理了消息?
大多數(shù)聲稱保證交付的框架和協(xié)議實際上提供了類似于第4點和第5點的內(nèi)容。雖然這聽起來很合理,但它實際上有用嗎?要理解其含義,請考慮一個簡單實用的示例:用戶嘗試下訂單,一旦它成功寫在訂單數(shù)據(jù)庫中的磁盤上。我們就聲明它已經(jīng)成功處理。
如果我們依賴于成功處理消息,則只要訂單已提交給負責驗證它的內(nèi)部API,處理它并將其放入數(shù)據(jù)庫,actor就會報告成功。不幸的是,在調(diào)用API之后,可能會發(fā)生以下任何一種情況:
??? ?主機可能崩潰。
??? ?反序列化可能會失敗。
??? ?驗證可能會失敗。
??? ?數(shù)據(jù)庫可能不可用。
??? ?可能會發(fā)生編程錯誤。
這表明發(fā)送的保證不會轉(zhuǎn)化為domain級保證。我們只想在訂單實際完全處理和存儲后報告成功。可以報告成功的唯一實體是應用程序本身,因為只有它對所需的domain保證有了解。沒有通用框架可以弄清楚特定domain的細節(jié)以及在該域中被認為是成功的。
在這個特定的例子中,我們只希望在成功的數(shù)據(jù)庫寫入后發(fā)出成功信號,數(shù)據(jù)庫確認訂單現(xiàn)在已安全存儲。由于這些原因,Akka將保證的責任提升到應用程序本身,即您必須使用Akka提供的工具自行實現(xiàn)它們。這使您可以完全控制要提供的保證。現(xiàn)在,讓我們考慮Akka提供的消息排序,以便于推理應用程序邏輯。
二、消息排序
在Akka中,對于給定的一對Actor,直接從第一個發(fā)送到第二個的消息將不會被無序接收。這強調(diào),這種保證僅適用于將tell的operator直接發(fā)送到最終目的地,而不是在使用mediators時。
如果:
??? ?Actor A1發(fā)送消息M1,M2,M3到A2。
??? ?Actor A3發(fā)送消息M4,M5,M6到A2。
這意味著,對于Akka消息:
??? ?如果發(fā)送M1,必須在M2和之前發(fā)送M3。
??? ?如果發(fā)送M2,必須在之前交付M3。
??? ?如果發(fā)送M4,必須在M5和之前發(fā)送M6。
??? ?如果發(fā)送M5,必須在之前發(fā)送M6。
??? ?A2可以看到來自A1交錯信息的消息A3。?
??? ?由于沒有保證傳遞,任何消息都可能被丟棄,即沒有到達A2。
這些保證達到了良好的平衡:讓一個Actor的消息按順序到達對于構(gòu)建易于追溯的系統(tǒng)是方便的,而另一方面允許來自不同Actor的消息交錯到達提供了足夠的自由來有效地實現(xiàn)Actor系統(tǒng)。
?
總結(jié)
以上是生活随笔為你收集整理的Akka之在IoT系统中使用Actor(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四层负载均衡与七层负载均衡
- 下一篇: Java获取当前线程的名字以及为线程命名