非同步程式設計模型的思考

arvin-hermit發表於2021-11-01

WX20211101-190630@2x.png

隨著移動網際網路的迅猛發展,我們對於服務的響應和併發要求越來越高。在這樣的背景下催生了形形色色的併發問題、例如C10問題就是非常典型的問題。對於這些形形色色的併發問題,人們演化設計出多種非同步程式設計的模型。所謂的併發是指在同一時間段內程式能交替執行。

在開始之前有這麼幾個問題需要探討,什麼是非同步程式設計模型、非同步程式設計能解決哪些問題、如何設計出一個非同步程式設計模型。

同步/非同步:是指程式自始至終都在用一個時間線上執行,非同步則是我程式是主時間線上出現了別的時間線分支。

非同步程式設計的宗旨:是高效地解決併發問題,獲得更高的併發請求

非同步程式設計具體實現方案

  • 事件輪詢

將資料互動過程中出現的各種事件註冊到一個事件佇列中,再由一些其他的執行緒來非同步消費處理

  • 回撥

在上述的事件佇列中,其實有個問題,往事件佇列中註冊一個事件之後,等該事件被觸發的那刻,誰來處理後續的業務邏輯?對於這個問題的解決方式就是“回撥”,現在高階程式語言都支援“回撥”功能。有了“回撥”,開發者可以在事件觸發前將回撥函式和事件繫結起來,等事件觸發那一刻,查詢出註冊好的回撥函式在去執行回撥函式的邏輯。至此通過回撥就輕鬆實現了非同步程式設計模型。

  • 協程

雖說有了回撥就就能滿足非同步程式設計,但是回撥帶來的問題也相當多,比如回撥中巢狀回撥(地獄回撥)、程式碼不符合人類思維、難於開發維護等。其實人類程式設計思維還是習慣於同步的程式設計邏輯,在程式碼按照書寫的順序一行一行去執行,每次執行結束都能有個返款!!!那麼說到這裡有沒有一種可能?就是我既能達到非同步的效果還能書寫同步的程式碼,換言之:就是用同步的程式碼書寫非同步的情懷!!!答案是肯定的,協程真是這樣背景下出現的一個將非同步回撥的方式轉化為同步程式碼、但是又有非同步功能的技術。協程是一種輕量級執行緒,排程的邏輯完全就交給使用者去控制。這樣使用者就可以在遇到同步IO的時候 ,掛起當前協程轉而執行下一個協程,整個程式碼邏輯都是順序書寫,被掛起的協程,等待下次再次排程執行。

在這邊一起梳理一下市面上主流語言和軟體的一些非同步程式設計模型

nginx 是多程式+單程式reactor非同步模型,網路請求事件都有reactor執行緒接管註冊分發給worker程式去執行

redis 單執行緒 reactor非同步模型 也是事件分發註冊非同步程式設計

netty 單執行緒reactor非同步模型

swoole 多執行緒reactor+多程式worker

nodejs 單執行緒+eventLoop

Golang 單執行緒Reactor+多執行緒協程

任何技術方案都是在歷史長河中演化而來,因此瞭解一門技術或者方案,最好能瞭解一下他的前世今生!!!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章