23 August 2011

簡而言之 Akka,是一個 inter-server computation framework。它的官網列出一堆有的沒的 "功能" (但能做什麼應用沒說),一付好像要改變整個開發生態一樣。

但 Akka 只適合拿來做 server 間的運算,因為它沒有用戶的 client (mobile/flash/web....etc),所以使用上其實很局限的。好了,下一個問題來了:

你的需求是自己寫 server cluster 嗎?

  1. 自己寫 server 和 cluster
  2. 自己寫 server,但是不是 cluster
  3. 不自己寫 server 也自己不寫 cluster。

我想第一種需求少的可憐,但這是唯一比較適合 Akka 的系統,第二種則是少數,而且通常都是寫個 socket server 就好了,也沒多大,這樣的需求只需要 JBoss netty,而不是 Akka。第三種應該是最多的,大家都是拿現成的 apache / tomcat / RDBMS / NoSQL / hadoop / rabbitmq / jabber / solr .... 等等來兜,很少有需求需要自己苦幹實幹打造 cluster,尤其現在幾乎是 web 服務的天下,更是如此。

Akka 的另一個面向是 Actor,event driven 式的開發。我自己寫遊戲寫了兩三年了,每天與 event 為伍,反到是沒什麼特別的感覺。不用寫 synchronize 和 java.util.concurrent 還蠻不錯的,你可以用 single thread 的思考方式來寫你的應用,唯一的要求是傳遞的訊息都是要 immutable 的。另外,用 event 的方式開發時,程式碼會朝另一種複雜度走:

  • 在結構上會偏 pattern match 而不是 polymorphism (所以 Java 上比較慘)
  • 在相依性上則可以減到很低,但這也意味你很難看出整個流程
  • 最後,能用 single thread 的方式思考也代表你直接寫出來的程式碼其實是處處 synchronized,你必需自行找出幾個瓶頸處,使用 router/load balancer 等技巧解開。

總之使用 Actor 後,思考的方式會變。這有比較好嗎?我持保留態度。因為即使 Actor 包裝過了,concurrent 的程式也不是一般人能碰的,而且你還是得懂 multi-thread 的概念才行。這就像是 ORM 可以爽爽用,但你不懂 SQL 遲早還是會撞牆,你還是得深入了解 SQL 才行。

話說回來,又有多少人的需求是 concurrent 的?大多數的 server 需求多是 stateless web server,concurrency 都交給 web server / db 做完了,不用自己寫。最近到有個新趨勢是 async web server,這個需求就很適合 Akka 來做。不過還是一樣,大家只會選做好的 server,而不會自己用 Akka 刻。

前面提到 Akka 適合 inter-server 的運算。這是因為 Akka 提供超便利的 Remote Actor。要叫遠端 server 做事嗎?跟寫 local actor 一樣,開了就連上,直接開始傳訊息,什麼繁雜事都不用做。不過 Remote Actor 的好處也到此為止了,其他寫 cluster 時最需要的 Fail over, Replicate, Load balance, High Availability 一樣也沒有,你通通得自己寫 (那特地選 Akka 的用意是....? 我幹嘛不一開始就用 Netty 自己寫?)。沒這些高級功能就算了,最慘的是 Remote Actor crash 時不會通知! ,遠端斷了線或出錯,本機端通通不知道,這種僅支援單向的聯結,多了很多麻煩的事要處理....

講 Akka 就一定會提到 Let it crash,這是 Akka CTO Jboner 每次演講都會一提再提的概念。Let it crash 在實作上就是 -- Actor 出了 exception,它馬上 crash,重建一個新的,讓所有的 state 歸零,重新開始。對於這樣處處可以砍掉重練的思考方式我目前還不能體會。而且我也是有點懷疑砍掉重練的做法,有很多時候是一小部份的資料造成錯誤的,但卻要捨棄所有做過的東西全部重來 (就像是用戶開了三層的視窗、或逛到第五層迷宮,只因為小錯誤就要一切從頭,用戶不暈倒才怪)。

Let it crash,我目前可以 想像 的架構是,將一個功能切碎成一大堆的子功能,每個子功能交給不同的 Actor 執行,這樣如果 crash 時損失就比較少了,不過程式碼的複雜性/負載平白無故的增加 (本來一行 method call,變成要建立一個專用的 actor...),這實在很難說是一個更好的架構。

其他的很時氅的什麼 Software Transactional Memory 的功能我還沒碰過,不過我很懷疑 STM 的實用性。通常記憶體內的 state 壞了整個丟掉,重新再來就好,只有像 persistence 會留下半毀的資料才需要考慮 transaction。STM 個人認為像是耍花腔,重看不重用。

Akka 雖然已經 1.0 了,但是 API 變動的幅度還是很大,1.1 到 1.2 又 deprecate 一狗票 API,所以還不是很成熟,而 Akka 大概會在年底推出 2.0 ,那時候 Remote Actor 就會有 Fail over, Replicate, Load balance 等等夢幻的功能。還沒出手的玩的,建議等到 2.0 再開始玩吧,反正 1.x 的 API 到時又會丟掉一大堆。當然如果你跟我一樣現在就要寫 cluster,那就硬著頭皮直接衝吧。

ps. 我使用 Akka Java API 開發,不是用 Scala


回響

可以用 Tag <I>、<B>,程式碼請用 <PRE>