深入到骨子裡的分散式和微服務化程式語言
分散式和微服務化,已經大行其道很久了。現在很多專案動不動就說做成微服務,不管不顧自己的專案性質,和相應的工具鏈支援。關於微服務,我還是很喜歡 Martin Fowler 大叔在 ofollow,noindex">MicroservicePremium 裡說的:
my primary guideline would be don’t even consider microservices unless you have a system that’s too complex to manage as a monolith.
微服務最基本,最核心的點是什麼?服務切分。一個能很好切分服務的架構師,即便是讓他用 Monolith 的方式搭建系統,模組的劃分也應該是很清晰的。
那麼,假如你手上擁有的已經是 JAVA 界當前開發效率最高,開發約定最統一的 Springboot 實現的一個 Monolith 系統,如果要把它分隔為幾個獨立的服務,你覺得會有多簡單?除了複製一些配置,切分新建幾個 Application 這些體力活外,模組間的通訊方式則可能需要有很大的改變。原來的 Java 程式碼呼叫,現在可能要改成 http 介面,grpc 等,即便不需要對外提供服務。
在 Elixir 裡,如果規劃的好,模組的切分一開始就通過 GenServer 等使用訊息傳遞的方式來呼叫,後期的微服務化簡直就是拆一下檔案目錄就差不多了,並不需要再大費周章改介面,統一資料傳輸格式等。Elixir 的 Node 節點註冊,Process 註冊、管理和通訊,為打造微服務化和分散式的系統提供非常好的支援。
更難得的是,Elixir 坐擁了 Erlang 傳承的寶藏,一籃子的工具庫,讓程式碼,服務間的呼叫和監控變得非常容易。這一套工具可以說是歷經幾十年產品線上磨練的官方套件,不必像其它語言那樣到處蒐羅組裝開源工具,或者自研。
比如,我現在只是實現一個計數器,你每次可以向它獲取下一個可用的數字,它會一直自增下去。如果你不想每次自增的間隔是 1,那可以設定其它間隔。
這麼簡單的一個應用,可以算是一個微服務了吧?我們還可以怎麼把它切分為更細的服務嗎?我們還可以把它分成三部分:
- 實現自增,和間隔設定邏輯的業務服務
- 儲存資料狀態的服務
- 監控這兩個服務的 Supervisor 服務,假如業務邏輯出錯,負責重啟
下面這幅圖應該基本可以說明整個應用是如何運作的了。
你可以看到,如果我把自增的間隔故意設定為非數字,導致服務意外退出,背後的 Supervisor 服務會將它悄悄的重啟,並按照編寫好的邏輯,把 Server 的內部狀態資料儲存到資料服務,以便重啟時讀取。等我重新設定一個正確的數字自增間隔後,就可以接著獲取新的號碼了。
在 Elixir 的互動控制檯 iex 下,敲入 :observer.start()
這個命令,就可以監控整個系統的執行狀態,包括有哪些 Application,哪些 Process,Application 記憶體使用情況,內部資料狀態(State)等。
總的來說,Elixir 的訊息呼叫機制,Application 的組織方式,Process Supervision 和節點的架構方式,豐富的系統工具,真的是從骨子裡散發出微服務的光芒。資料的 immutability 更是讓分散式資料處理更安心,不用擔心一些不必要的多執行緒問題。
Elixir 的作者 José Valim,在 Elixir in times of microservices 這篇文章中介紹更清楚詳細,推薦一讀。