這篇開始,會比較偏向個人心得和見解,裡面若有些知識上的理解錯誤,也請各路朋友幫忙提醒一下,或與各位看倌的認知有出入實屬正常,歡迎交流想法。
goroutine 一直是我想很講的一個主題,雖然比較細節的部分,需要可能輔助以官方文件講才比較清楚。
有時候對於某些朋友,process、thread、goroutine,對於此三者的認識還是混淆在一起,心裏多少OS。
也許有人覺得開發上不一定要了解這三者的區別,但對於環境和架構的評估,沒有這方面的理解,筆者認為會對於狀況的評估有時候偏差甚遠。
舉個周遭的例子,有人喜歡講線程,啟動process,口頭上會講成『啟動線程』,就以前我們在用的php背景排程程式來講,是沒有太大的差異沒錯,裡面沒有用php多線程的寫法。你起一個process,等於起一個線程,也就是一個thread,單線程的作業模式。
all right,所以為了加快處理速度,你起了100個process,說是起100個線程.......恩,好吧。
但是你在起go的排程背景程式,也是起100個process當作起100個線程,那真的是大錯特錯,裡面的goroutine一但開出去,會使用幾個thread只有天知道,舊的評估方式完全是無法套用在go的程式上面。
thread 與process的相關知識是屬於computer science的OS,也就是『作業系統』的部分,筆者覺得不算特別困難,可以的話,花費一點時間學習一下應該是很有幫助的。
routine的概念與做法,可以說是用軟體突破硬體的限制,充分的發揮硬體真正效能,所以當瞭解到thread的物理限制上可以突破,這點是當初是令人十分地震驚,不過當你不知道這些東西彼此的差異,可能沒什麼感覺。
就拿『無窮迴圈』來比較好了,因為有了goroutine,golang可以怎麼玩?請看倌們想想自己寫的其他語言,可以開幾個無窮迴圈,像golang這樣玩。
概念上來想,寫個for無窮迴圈,程式執行就會卡住是吧,那麼你的程式能寫幾個這樣的無窮迴圈?
如果用multithread的寫法,你也許可以多寫幾個無圈迴圈,10個?100個?1000個?
以熟悉的LAMP架構為例,請你試著在apache上的php server寫看看,收到request後,就進入某個無窮迴圈的程式碼卡在那裡,試試可以卡住幾個無窮迴圈,機器不會燒起來?
Golang的話,一個goroutine可以寫一個無窮迴圈卡住,那麼可以開幾個goroutine呢?幾十萬個,若記憶體夠大,挑戰上百萬個也是可以。
把goroutine用得理所當然,用得喪心病狂,可能是很多熟悉這個語言的開發者在做的事情了,初入此道的我原先還在小心翼翼,擔心多開一點goroutine就會有負面的影響,機器會負擔不了云云,還在用thread的概念去想它的資源分配。
但事情不是這樣的,為什麼我想用無窮迴圈舉例goroutine?是因為在研究websocket連線的時候,發現人家底層是怎麼幹的。
websocket連線一旦建立,就一直保持連線著,所以對於server,每個連線進來,基本上就會開一個goroutine跑無窮迴圈,保持著連線。
基本io就是讀和寫,所以設計上以melody package來講,原本保持連線的goroutine當作read,等待有資訊從外面傳進來,另外再開啟一個goroutine跑無窮迴圈做write的工作,一但有資料寫入,即可立即傳到client端。
所以一個websocket連線,基本就會有兩個goroutine,而且是兩個跑著無窮迴圈的goroutine,那麼簡單的一萬條連線呢?就會有兩萬個跑著無窮迴圈的goroutine在上面。
看了看機器狀況,這樣好像也並不是什麼特別嚴重的負擔,儼然goroutine的應用,已經是另一個層次的考量方式。
再搭配channel,goroutine已經是golang各處的日常應用,在php的設計概念已經不能直接在golang上的程式設計套用。
能夠更了解Golang的設計方式,與Golang的內容知識,才能夠設計相符的應用程式,將該語言的優點與效益發揮出來。