scala的akka和go的goroutine有什麼區別,分別更適合哪些應用場景?
akka和goroutine哪一個具有更高的並發能力?cpu密集型和io密集型的任務更應該使用哪一種技術?
其實比較Akka和goroutine並不太合適,二者不是同一個層面的東西。應該比較Akka的Actor模式和Go的CSP模式。
二者都是通過消息通信的機制來避免競態條件,但具體的抽象和實現上有些差異。
- CSP模型里消息和Channel是主體,處理器是匿名的。
也就是說發送方需要關心自己的消息類型以及應該寫到哪個Channel,但不需要關心誰消費了它,以及有多少個消費者。Channel一般都是類型綁定的,一個Channel只寫同一種類型的消息,所以CSP需要支持alt/select機制,同時監聽多個Channel。Channel是同步的模式(Golang的Channel支持buffer,支持一定數量的非同步),背後的邏輯是發送方非常關心消息是否被處理,CSP要保證每個消息都被正常處理了,沒被處理就阻塞著。
- Actor模型里Actor是主體,Mailbox(類似於CSP的Channel)是透明的。也就是說它假定發送方會關心消息發給誰消費了,但不關心消息類型以及通道。所以Mailbox是非同步模式,發送者不能假定發送的消息一定被收到和處理。Actor模型必須支持強大的模式匹配機制,因為無論什麼類型的消息都會通過同一個通道發送過來,需要通過模式匹配機製做分發。它背後的邏輯是現實世界本來就是非同步的,不確定(non-deterministic)的,所以程序也要適應面對不確定的機制編程。自從有了並行之後,原來的確定編程思維模式已經受到了挑戰,而Actor直接在模式中蘊含了這點。
從這樣看來,CSP的模式比較適合Boss-Worker模式的任務分發機制,它的侵入性沒那麼強,可以在現有的系統中通過CSP解決某個具體的問題。它並不試圖解決通信的超時容錯問題,這個還是需要發起方進行處理。同時由於Channel是顯式的,雖然可以通過netchan(原來Go提供的netchan機制由於過於複雜,被廢棄,在討論新的netchan)實現遠程Channel,但很難做到對使用方透明。而Actor則是一種全新的抽象,使用Actor要面臨整個應用架構機制和思維方式的變更。它試圖要解決的問題要更廣一些,比如容錯,比如分散式。但Actor的問題在於以當前的調度效率,哪怕是用Goroutine這樣的機制,也很難達到直接方法調用的效率。當前要像OO的『一切皆對象』一樣實現一個『一切皆Actor』的語言,效率上肯定有問題。所以折中的方式是在OO的基礎上,將系統的某個層面的組件抽象為Actor。
如果純粹從調度的層面分析,正如 @邱鵬滔 的回答,Akka是在線程池基礎上實現調度的,但線程是有限的,所以Akka的Actor中要避免任何阻塞操作,要麼用Akka提供的非同步框架,要麼通過Future-callback機制,轉換成回調模式。而Goroutine是用戶態的線程,創建和切換成本都比較小,可以把非同步的callback機制轉換為同步模式,對開發比較友好些。更詳細的分析請參看我的文章: 並發之痛 Thread,Goroutine,ActorAkka是基於線程池實現的actor,如果你的actor里存在長時間的io阻塞導致線程耗盡,會使所有的actor都卡住,所以Akka是很害怕那種長時間io阻塞的操作。
其中Actor和CSP是不太一樣的模型,並且CSP在容錯以及集群方面不如Actor模型。
其中CSP,還有GO語言我推薦:
《Go語言實戰》—— GO精粹,對Go的協程進行了非常非常詳細的解釋,用了兩章,圖文並茂。
而對於Akka,我推薦下面幾本書,建議都買來看看:
《Java並發編程實戰》—— 基礎,因為 Akka 默認使用的是Java 7所引進的ForkJoin線程池,目前最新的實現是自己內嵌的一個ForkJoin線程池。
《Erlang趣學指南》—— 基礎,因為學習 Akka不得不了解 Actor 模型的來源,以及實現。這本書生動有趣,不但涵蓋了基礎知識還包含了OTP的內容,即 Akka 集群。
《Akka 入門與實踐》 —— 入門,本書是入門的 Akka 書,可以保證您快速地上手 Akka,譯者也是摩根的大牛,清華高材生。
《反應式設計模型》—— 進階,本書我們還在翻譯,原書是前 Akka Tech Lead 編寫的 《Reactive Design Patterns》,這本書可以幫助你了解更深的理論層次的知識。
《領域驅動設計 ——軟體核心複雜性應對之道》 —— 進階,這本書雖然不是教你具體的 Akka代碼,但是對你如何使用 Akka 來解決複雜的現實的業務問題幫助非常大。
以上是個人的一點建議,雖然我也是為了擴大我們 Akka 社區的圈子:)
當然如果你想要了解 Netty 也可以關註:如何評價《Netty實戰》這本書? - 知乎
akka是actor model
go的goroutine是一個協程機制
這樣說你肯定沒概念,也不好直接比,我們找一個java上的actor model來對比
你看啊,vert.x就是java寫的actor model,vert.x的handler就是actor model裡面的actor
vert.x發展了actor,提出了一個verticle的概念,所以vert.x的性能比akka要強
其次寫起來也方便很多
但是呢,它遇到一個問題,就是非同步帶來的回調的問題
腫么辦?
所以kotlin提出了跟go的goroutine一樣的東西,就是coroutine
藉助coroutine,我們可以讓線程當前執行暫停(suspend)然後resume
這會有一點點性能上的消耗,3%-5%左右
但是前面說了,verticle提出之後,比純粹的actor model性能要有所提升
所以這一升一降,其實總體應該還是升的
從techempower的benchmark上看,vert.x性能明顯比akka要強不少
哪怕降個5%,也不會有太大變化
適合場景:更適合io bound的場景
cpu bound你需要通過降低演算法複雜度來實現,而不是通過非同步來實現
goroutine實現的是csp,通過獨立的channel傳遞信息。akka實現的是actor,消息通過actor擁有mailbox接收。僅僅上面的不夠特化。akka是通過線程池實現的actor,線程是有限的,假如一個actor阻塞一個線程(例如一個阻塞io),可能會影響其他的actor,類似於協調型的調度。而goroutine運行在用戶態線程上,受go運行時搶佔式調度。
推薦閱讀:
※Go語言做Web應用開發的框架,哪一個更適合入門?
※多線程情況下 很多變數 頻繁訪問 難道每個都要加鎖訪問嗎?
※如何看待 Dropbox 從 Go 轉向 Rust ?
※nodejs與go語言比較如何,它們的發展前景怎樣,網站後台開發,選擇nodejs好還是go好?
※選擇學習 C 語言、Go 語言、C++11 各有哪些優缺點?