我正在使用Akka構建我的運行時消息系統。但它經常遭受尷尬的境地:很多郵件都是以!
發送的,很難追蹤業務邏輯。 從Programming in Erlang
這本書中,我們不建議將消息公開給其他人,而是用一個函數封裝actor消息,並用export([func1/1])
或其他東西將其導出。如何避免在使用Akka構建程序時隨處傳遞原始消息?
那麼,是否有可能在Akka中使用函數調用模式?
使用Akka構建大型系統時,如何閱讀包含如此多消息的代碼?
我正在使用Akka構建我的運行時消息系統。但它經常遭受尷尬的境地:很多郵件都是以!
發送的,很難追蹤業務邏輯。 從Programming in Erlang
這本書中,我們不建議將消息公開給其他人,而是用一個函數封裝actor消息,並用export([func1/1])
或其他東西將其導出。如何避免在使用Akka構建程序時隨處傳遞原始消息?
那麼,是否有可能在Akka中使用函數調用模式?
使用Akka構建大型系統時,如何閱讀包含如此多消息的代碼?
新的實驗阿卡類型支持走一段很長的路要走,以幫助瞭解和跟蹤業務邏輯:
https://doc.akka.io/docs/akka/2.5/scala/typed.html
這樣做是什麼讓你編碼協議,與在類型系統中的行動者,這可以使您在閱讀代碼時更容易理解系統的工作原理。
另一個選擇是使用Cinnamon(一個Lightbend商業庫)來跟蹤消息,這可以讓你理解運行時的控制流程。這裏有一個關於它的博客帖子:
https://developer.lightbend.com/blog/2017-05-08-cinnamon-2-4-with-opentracing-integration/
如果你做了很多詢問你的演員,一個常見的模式是把背後返回期貨的方法。例如:
class MyService(actor: ActorRef) {
def doSomething(msg: Something): Future[Result] = {
(actor ? msg).mapTo[Result]
}
}
當然你也可以適用於經常告訴,除了你的返回類型將是Unit
同樣的事情。
最後,在阿卡一個常見的模式是把所有的消息類中的演員同伴對象:
object MyActor {
/** This message does something */
case class MessageOne(foo: String)
/** This message does something else */
case class MessageTwo(bar: String)
}
class MyActor extends Actor {
import MyActor._
override def receive = {
case MessageOne(foo) =>
...
case MessageTwo(bar) =>
...
}
}
雖然也許這不符合下列業務邏輯的幫助,但它更容易對於新系統的人來說,通過將所有消息(與文檔)放在一個地方,可以瞭解如何與演員對話。
另外一個關於結構化代碼的詞 - 演員應該有一個有限的責任和一個明確的協議。一個精心設計的基於Akka的系統不會要求您一次瞭解所有消息的全部流程,應該直接推斷每個演員的個人身份。仔細使用actor層次結構來抽取子進程作爲子actor可以真正幫助到這裏。換句話說,如果爲了理解你的系統如何表現,你需要了解成百上千個演員之間的數千條消息是如何流動的,那麼你肯定有設計問題,並且需要重新考慮如何讓你的演員分手轉化爲可以像構建模塊一樣輕鬆放置在一起的獨立單元。
你可以做同樣的事情Erlang做,並隱藏所有消息傳遞函數。或者換句話說,你不應該與演員打交道,而應該處理一般的(領域抽象)類,並且只使用演員作爲下屬實現。
case class Cat(name: String)
trait Shelter {
def leave(cat: Cat): Unit
}
class ActorShelter extends Shelter with Actor {
var cats = List[Cat]()
def leave(cat: Cat) =
this.self ! cat
def receive = {
case cat: Cat =>
cats = cat :: cats
}
}
這將允許您在您的代碼中使用Shelter
而不知道它是演員。
當然,您仍然需要決定是否要在!
的所有演員表中返回Unit
,或者只是參考自己。如果您在?
的電話上返回Future
,或者您會等待實際價值。
直接但有效 – LoranceChen
但是,一個問題是,當我創建一個'ActorShelter'我只得到一個'ActorRef'類型。我怎樣才能得到'住房'? – LoranceChen
這是一個很好的觀點,並且稍微複雜一些。在Erlang中,你可以產生一個新的進程/ actor,在Akka你必須在一些上下文(系統或其他已經存在的actor)中完成。它可以根據你的應用程序結構而有所不同,所以沒有一個適合所有人的解決方案。我會盡量調查一下,也許更新我的答案。 – mpm
*當然*有一些比這更好的系統。我的意思是,它的阿卡。 Erlang一直在......並且......認真? – zxq9
偉大的建議!想一想將物體置於物體中可能並不總是很有效的解決方法。比如,如果我有一個案例類消息需要在兩個或更多的actor中使用define.Besides,我認爲typed actor有其限制,因爲我們不能保證所有收到的消息都是很好的類型,它屬於actor的行爲。 – LoranceChen