聊聊微服務叢集當中的自動化工具
本篇部落格主要介紹了自動化工具這個概念,在微服務叢集當中的作用,算拋磚引玉,歡迎大家提出自己的見解。
寫在前面
在瞭解自動化工具的概念之前,我們先了解一下微服務和叢集的概念。
什麼是微服務
這個概念其實有些廣泛,而我的知識廣度也有限,我會盡量用通俗的語言來描述什麼是微服務,什麼是叢集,以及為什麼我們需要微服務叢集 。為什麼需要叢集可以去看看《小強開飯店-從單體應用到微服務》,這篇文章用非常通俗的語言和配圖,通過一個漫畫故事簡單的解釋了為什麼我們需要微服務叢集。
微服務
傳統的後端服務多為單體應用,例如使用Sprint Boot或者Node又或者Gin搭建的簡單的後端服務,在此基礎之上,實現了基本的業務之後再部署到伺服器上執行起來,這就成為了一個單體應用。
隨著業務需求的增加、業務程式碼慢慢的累加,單體應用變的也越來越大。同時各個模組的大量業務程式碼相互糾纏在一起,開發以及維護變得尤其困難。想象一下一個剛剛加入專案的新人看到相互糾纏的、邏輯複雜的業務程式碼的絕望。
這個時候我們就需要了解微服務的概念了。如果想要講這個龐大的單體應用可維護、可擴充套件以及高可用,我們就需要對單體應用按照模組進行業務拆分 。
例如將使用者相關的所有邏輯單獨搞成一個服務,又例如訂單、庫存可以搞成一個單獨的服務。這樣一來,業務程式碼被分散到幾個單獨的服務中,每個服務只需要關心、處理自己這個模組的業務邏輯。這樣一來,業務程式碼的邏輯清晰,對開發人員來說,條理以及思路都很清晰。即使是後加入的專案開發人員,面對業務邏輯清晰的程式碼也十分容易上手。
微服務的拆分
其實我看到很多的文章關於微服務的介紹就基本到這了,但是還有個值得提的概念。首先,微服務怎麼拆分其實是沒有一個標準的。
你按照什麼樣的粒度去拆分你的服務其實是跟業務強相關的。並不是說一個服務的程式碼一定就很少,根據你的業務的量度,例如你的系統使用者量特比的大,那麼一個使用者服務的程式碼量上千上萬行我覺得都很正常。
當然我也見過使用者不是很多,只是為了高可用和快速定位,而將系統拆分的非常細的系統,有好幾十個服務。那麼問題來了,有這麼多服務,前端需要去維護的後端API的地址就相當的龐大了。
我們暫且先不討論所有拆分的服務是否執行在同一個伺服器上,就算是,那也得是不同的埠。前端也需要根據後端拆分的服務模組,去維護這樣一張API的對映表。所以我們需要提出一個BFF,AKA Backend For Frontend.
BFF
其實BFF層最初被提出來,其實不是為了微服務拆分模組中提到的目的。其設計的目的是為了給不同的裝置提供不同的API。例如一個系統的後端服務,同時需要支援不同的終端,例如移動端的iOS和Android,PC端。
這樣一來,可以根據不同裝置上的需求來提供對應的API,而且不需要更改我們現有的微服務。
這樣一來,我們的底層服務群就具有了很強的擴充套件性,我們不需要為一個新增的客戶端來更改底層的服務程式碼,而是新增一層BFF層,來專門針對該終端型別去做適配。
大家從上面的圖可以看出來,客戶端都沒有直接訪問我們的底層服務。而是都先經過BFF層提供的介面,再由BFF層來根據不同的路由來呼叫不同的底層服務。總結一下,加了BFF層的優點如下。
- 擴充套件性強,可以適應不同的客戶端
- 統一的API管理,客戶端無須再維護API的對映表
- 可做集中鑑權,所有的請求都會先經過BFF,可在這一層對呼叫介面的合法性進行驗證
當然,BFF也有缺點。
- 處理不當會有大量的程式碼冗餘
- 因需要呼叫不同底層的服務而增大開發的工作量
當然在實際的生產環境下,我們也很少會將BFF層直接暴露給客戶端。我們通常會在BFF層上再加一層閘道器。閘道器可以在請求還沒有到BFF的時候,實現許可權認證,限流熔斷等等其他的功能。
叢集
上面簡單的聊了一下什麼是微服務,現在我們來聊聊什麼是叢集。我們知道,當一個單體應用大的已經很難維護的時候,最好的辦法就是將其拆分成微服務。這樣有什麼好處呢?
- 便於維護。每個微服務專注於自己這個模組的業務邏輯,不會存在各個模組的業務邏輯纏在一起的狀況。
- 提高可用性。當單體應用掛掉的時候,我們系統的所有模組都將不可用。而拆分成微服務就可以儘量的避免這個問題。單個服務掛掉了,不會影響到其他服務的正常執行。
- 便於運維。單體應用重新部署的時候,會使整個系統不可用。而在微服務中,單個服務重新部署的代價明顯要小的多。
概念
說了這麼多,我們來給叢集一個概念吧。叢集就是將同一套服務部署在不同的伺服器上,對外提供服務。
例子
我舉個具體的例子。例如我們使用Docker Swarm來提供容器的叢集服務。
在Docker Swarm中有節點這樣一個概念,凡是運行了Docker的主機都可以主動的建立一個Swarm叢集或者加入一個已經存在的叢集,一旦加入,這個主機就成為了這個叢集中的一個節點。在叢集中節點分為兩類,分別是管理節點(manager)和工作節點(worker)。我們可以用Portainer來管理Docker主機和Swarm叢集。
我們以一個叢集中的請求來舉個例子。
首先進入系統之後會先進入一個統一鑑權的系統去鑑權,鑑權成功之後就會到我們的微服務閘道器,如果這個地方還有系統自己的特殊鑑權的話,再次進行鑑權。之後閘道器這邊會將我們的請求根據配置的路由來分發到具體的某個伺服器上的某個容器中。
自動化工具
自動化工具的都包含了哪些技術呢?
其中的Java只是一個類比,代表你的程式語言。微服務中其實不是很關心具體用的什麼語言,甚至每個服務都用不同的技術棧都行。
那麼自動化工具是什麼呢?其作用是什麼?在叢集中扮演了什麼樣的角色呢?我們通過一張圖來簡單的瞭解一下。
構建
簡單的梳理一下邏輯。
- 首先自動化工具將Jenkins構建所需要的引數組織好,呼叫Jenkins的構建API,並記錄構建操作到自動化工具的資料庫
- 然後Jenkins用配置好的憑證去Gitlab的對應的專案的分支拉取程式碼,根據配置好的構建指令碼開始構建,記錄構建記錄到自動化工具的資料庫
- 構建好後再推送到docker的倉庫中,並記錄到自動化工具的資料庫
到此構建的邏輯結束。
其他的功能
自動化工具還可以直接在專案列表中,選擇檢視當前專案的日誌,而不需要每次重新開啟Kibana然後再加篩選filter。
自動化工具的專案設定中,我們還可以更改docker容器的配置,而不需要再去portainer中或者通過命令列去修改;如果想要命令列進入容器,首先我們得找到對應的service,然後找到對應執行的service例項,然後才能進入,而如果我們直接使用portainer的Api,在endpoint已知的情況下,可以直接將這個功能做到自動化工具中,直接使用webshell一鍵連線。
其好處是什麼呢?
- 對大部分開發遮蔽Swarm叢集。對專案中非管理員的開發遮蔽Portainer,因為這個許可權非常大,一旦不熟悉導致了誤操作,那麼有可能直接影響到線上的服務
- 統一許可權控制。在自動化工具裡做許可權以及環境的統一控制
- 上手成本低。比起直接操作portainer和Jenkins和Kibana,自己搭建的自動化工具十分容易上手
功能總結
總結一下,其功能主要為以下幾個。
- 構建
- 部署
- 回滾
- 檢視elk日誌
- 更改docker配置
- 管理叢集的環境、專案和容器
- 命令列連線具體專案的容器
- …...
看到這大家可能會有疑問。
- 構建?你的意思是我Jenkins是擺設咯?
- 部署?更改 docker配置?命令列連線具體專案的容器?我的Iterm2也是個擺設?
- 回滾?等於是我之前的docker映象的tag白打了?
- elk日誌?我的Kibana是拿來看新聞的嗎?
功能詳解
構建
其實在構建這塊,我個人認為自動化工具和Jenkins都很方便。而且自動化工具本身就是用的Jenkins,只不過是呼叫了Jenkins的API,傳遞了構建的引數,最終真正去構建的還是Jenkins。
只不過對於剛剛加入專案的測試來說,自己開發的Web UI對新人更加的友好,而且可以在自動化工具中做到許可權控制。
部署和回滾
部署在自動化工具的後端通過docker-client實現。首先我們根據配置,建立docker client。然後如果已經有在執行的服務了,就呼叫update service更新服務,否則就建立服務。
回滾與其本質相同,只不過是用了之前的引數和不同的tag。
elk日誌
首先,每個環境的配置中,會配置上kibana_host以及kibana_index,然後根據系統的projectKey,拼接成相應的Kibana日誌的url,然後使用iframe嵌入到自動化工具中。這樣一來就不用再手動的開啟Kibana再去設定對應的filter了。特別是當你係統特別多的時候,新增和刪除filter是很廢時間的。
更新容器配置
這裡也同樣是呼叫對應的API更新對應服務的配置,而不用登入portainer去修改。
同時,在自動化工具中還可以針對不同的環境配置不同的Base Setting。後續在該環境下新增的應用不用再單獨配置,直接繼承環境的Docker Setting即可。
管理叢集的環境、專案和容器
可以通過自動化工具統一的來建立和管理環境,同樣有三種環境,研發、測試、生產環境。然後可以在自動化工具中建立角色和使用者,分配給不同的角色不同的許可權來達到控制權限的目的。
命令列連線具體專案的容器
通常我們因為某個需求,需要進入到容器中檢視,然而此時我們就面臨兩種選擇。
- 通過portainer進入對應service,找個某個具體的container,點選連線
- 命令列到容器具體執行的某個伺服器上,然後再通過命令列連線
但是有了自動化工具,我們就有了第三種選擇。
- 點選連線
怎麼實現的呢?實際上就是通過endpointId去獲取到所有的container的資訊,然後遍歷所有的container,找到與當前選中的containerId相同的容器,獲取到其NodeName,這樣一來我們就知道當前這個容器到底執行在哪個節點上的了。
然後通過已有的資訊,構建WebSocket的url,最後前端通過xterm來建立ws連線,就這樣直接連線了正在執行的容器例項。
總結
自動化工具只是一種思路,一種解決方案,它的好處在上面也列出了很多。當然,它肯定也有壞處,那就是需要專門投入人力和資源去開發。
這對於人手緊缺和專案週期較短的專案組來說,十分的不現實。但是如果一旦有精力和時間,我覺得值得一試。同時,基於portainer的API,我們還有可能將更多與叢集相關的功能,整合到自動化工具上。
往期文章:
- 什麼?你竟然還沒有用這幾個chrome外掛?
- 手把手教你從零開始搭建SpringBoot後端專案框架
- 用go-module作為包管理器搭建go的web伺服器
- WebAssembly完全入門——瞭解wasm的前世今身
- 小強開飯店-從單體應用到微服務
相關:
- 微信公眾號: SH的全棧筆記(或直接在新增公眾號介面搜尋微訊號LunhaoHu)