微服務下的閘道器如何選擇

大魔王先生發表於2020-11-20

前言

自從換了工作以後,將近5個月沒有寫部落格了,這段時間經歷一個身份的轉變,從一個核心開發轉變為了一個專案的Leader,這種感覺說不上來的,雖說是有些感悟,但是更多的是一些困惑,但是有一點是明確的,站的高度或者角度不同,有些思考是不一樣的,有這種身份轉換的,大家可以做一些交流,嘿嘿!開啟我們的正題,最近專案要從第三方外包的手中轉成自有化的形式,我們準備採用微服務的形式去做這件事。之前也想寫這個系列的話題,整好趁著這次的改造來完成這個微服務序列的文章,首先我們來介紹下閘道器這個元件。

為什麼出現閘道器

微服務的架構體系中,可以簡單的看做是一個大應用拆分為多個小應用,小應用可以自成體系,可以擁有自己的資料庫、框架甚至於語言等等,各個小應用一般通過Rest介面的形式被第三方、H5或者APP去呼叫。這個時候必然會存在一種情況,某些頁面需要多個服務組合才能得到使用者需要的資訊。舉個例子:

在電商系統中,檢視商品詳情頁,這個商品詳情頁包含商品的詳情,價格,庫存,評論等,這些資料對於後端來說位於不同的微服務系統之中,後臺的系統是這樣來拆分服務的:
商品服務:負責提供商品的標題,描述,規格等。
營銷服務:負責對產品進行定價,價格策略計算,促銷價等。
庫存服務:負責產品庫存。
評價服務:負責使用者對商品的評論,回覆等。

我們不做任何處理的時候,呼叫的時候是這樣:


該處的缺點就是前端需要呼叫多次服務才能拿到我們想要的資料,為了解決這個問題我們可以做一層中間的聚合層,聚合層也就是我們通常所說的BFF(Back-end for Front-end),BFF可以認為是一種適配服務,將後端的微服務進行適配(主要包括聚合裁剪和格式適配等邏輯),實現上沒太大限制,能做請求轉發和資料轉化即可,升級以後框架是這樣的,之前我們系統處於這個階段:
升級以後的框架解決了多次呼叫的問題,但是這裡地方會存在如下幾個問題:
1.多個聚合層有很多跨橫切面的程式碼是重複的,比如安全認證,日誌監控,限流熔斷等,隨著時間的發展程式碼變得不可維護;
2.隨著訪問量、業務的增加,兩個BFF層也滿足不了我們的業務,需要抽象更多的BFF和採用叢集部署的方式;
接下來我們再次升級我們架構,如下圖:

這裡我們引入的我們本章的主角閘道器,由於閘道器的加入我們可以將所有的跨橫切面的程式碼通通抽象到閘道器層,這樣我們BFF層只需要關注服務適配的邏輯,另外也解決掉了之前業務單點、多節點的等問題,這個時候你可能又想,閘道器的部署也是單點了,這個時候你可以考慮在閘道器前掛一層NG或者F5,如果隨著業務發展閘道器管理的服務越來越多,也可以將閘道器按照業務域進行整體的拆分。
到這裡你一定了解到了為什麼需要閘道器,寫到這裡我突然想到某個偉人說的一句話,沒有什麼是加一箇中間層解決不了的,如果有,就加兩個……,BFF也好、閘道器也好都是我們的中間層。

閘道器選型

目前市面上根據技術棧實現的不同大概有如下一些閘道器:


接下來我們就簡單瞭解下以上5個閘道器:
Nginx: Nginx由核心和模組組成,核心的設計非常微小和簡潔,完成的工作也非常簡單,僅僅通過查詢配置檔案與客戶端請求進行 URL 匹配,用於啟動不同的模組去完成相應的工作。

Nginx 在啟動後,會有一個 Master 程式和多個 Worker 程式,Master 程式和 Worker 程式之間是通過程式間通訊進行互動的,如圖所示。Worker 工作程式的阻塞點是在像 select()、epoll_wait() 等這樣的 I/O 多路複用函式呼叫處,以等待發生資料可讀 / 寫事件。Nginx 採用了非同步非阻塞的方式來處理請求,也就是說,Nginx 是可以同時處理成千上萬個請求的。

還可以將 Lua 嵌入到 Nginx 中,從而可以使用 Lua 來編寫指令碼,這樣就可以使用 Lua 編寫應用指令碼,部署到 Nginx 中執行,即 Nginx 變成了一個 Web 容器;這樣開發人員就可以使用 Lua 語言開發高效能Web應用了。在開發的時候使用 OpenResty 來搭建開發環境,OpenResty 將 Nginx 核心、LuaJIT、許多有用的 Lua 庫和 Nginx 第三方模組打包在一起;這樣只需要安裝 OpenResty,不需要了解 Nginx 核心和寫複雜的 C/C++ 模組就可以,只需要使用 Lua 語言進行 Web 應用開發了。

Kong: Kong是一款基於OpenResty(Nginx + Lua模組)編寫的高可用、易擴充套件的,由Mashape公司開源的API Gateway專案。Kong是基於NGINX和Apache Cassandra或PostgreSQL構建的,能提供易於使用的RESTful API來操作和配置API管理系統,所以它可以水平擴充套件多個Kong伺服器,通過前置的負載均衡配置把請求均勻地分發到各個Server,來應對大批量的網路請求。


Kong主要有三個元件:
  1. Kong Server :基於Nginx的伺服器,用來接收API請求。
  2. Apache Cassandra/PostgreSQL :用來儲存運算元據。
  3. Kong dashboard:官方推薦UI管理工具,當然,也可以使用 restfull 方式 管理admin api。

Kong採用外掛機制進行功能定製,外掛集(可以是0或N個)在API請求響應迴圈的生命週期中被執行。外掛使用Lua編寫,目前已有幾個基礎功能:HTTP基本認證、金鑰認證、CORS(Cross-Origin Resource Sharing,跨域資源共享)、TCP、UDP、檔案日誌、API請求限流、請求轉發以及Nginx監控。


Kong閘道器具有以下的特性:
  1. 可擴充套件性: 通過簡單地新增更多的伺服器,可以輕鬆地進行橫向擴充套件,這意味著您的平臺可以在一個較低負載的情況下處理任何請求;
  2. 模組化: 可以通過新增新的外掛進行擴充套件,這些外掛可以通過RESTful Admin API輕鬆配置;
  3. 在任何基礎架構上執行: Kong閘道器可以在任何地方都能執行。您可以在雲或內部網路環境中部署Kong,包括單個或多個資料中心設定,以及public,private 或invite-only APIs。

Netfilx Zuul:Zuul 是 Netflix 開源的微服務閘道器元件,它可以和 Eureka、Ribbon、Hystrix 等元件配合使用。社群活躍,融合於 SpringCloud 完整生態,是構建微服務體系前置閘道器服務的最佳選型。

Zuul的核心是一系列的filters, Zuul 的核心是一系列的過濾器,這些過濾器可以完成以下功能:
  1. 身份認證與安全:識別每個資源的驗證要求,並拒絕那些與要求不符的請求。
  2. 審查與監控:與邊緣位置追蹤有意義的資料和統計結果,從而帶來精確的生產檢視。
  3. 動態路由:動態地將請求路由到不同的後端叢集。
  4. 壓力測試:逐漸增加指向叢集的流量,以瞭解效能。
  5. 負載分配:為每一種負載型別分配對應容量,並棄用超出限定值的請求。
  6. 靜態響應處理:在邊緣位置直接建立部分響應,從而避免其轉發到內部叢集。
  7. 多區域彈性:跨越 AWS Region 進行請求路由,旨在實現 ELB(Elastic Load Balancing,彈性負載均衡)使用的多樣化,以及讓系統的邊緣更貼近系統的使用者。

Zuul 目前有兩個大的版本:Zuul1 和 Zuul2
Zuul1 是基於 Servlet 框架構建,如圖所示,採用的是阻塞和多執行緒方式,即一個執行緒處理一次連線請求,這種方式在內部延遲嚴重、裝置故障較多情況下會引起存活的連線增多和執行緒增加的情況發生。


Netflix 釋出的 Zuul2 有重大的更新,它執行在非同步和無阻塞框架上,每個 CPU 核一個執行緒,處理所有的請求和響應,請求和響應的生命週期是通過事件和回撥來處理的,這種方式減少了執行緒數量,因此開銷較小。

Spring Cloud GetWay:Spring Cloud Gateway 是Spring Cloud的一個全新的API閘道器專案,目的是為了替換掉Zuul1。Gateway可以與Spring Cloud Discovery Client(如Eureka)、Ribbon、Hystrix等元件配合使用,實現路由轉發、負載均衡、熔斷等功能,並且Gateway還內建了限流過濾器,實現了限流的功能。


  Gateway基於Spring 5、Spring boot 2和Reactor構建,使用Netty作為執行時環境,比較完美的支援非同步非阻塞程式設計。Netty使用非阻塞的IO,執行緒處理模型建立在主從Reactors多執行緒模型上。其中Boss Group輪詢到新連線後與Client建立連線,生成NioSocketChannel,將channel繫結到Worker;Worker Group輪詢並處理Read、Write事件。

Soul: Soul是一個非同步的,高效能的,跨語言的,響應式的API閘道器。參考了Kong,Spring-Cloud-Gateway等優秀的閘道器後,站在巨人的肩膀上,Soul由此誕生!


Soul特徵:
  1. 支援各種語言,無縫整合Dubbo,SpringCloud。
  2. 豐富的外掛支援,鑑權,限流,熔斷,防火牆等等。
  3. 閘道器多種規則動態配置,支援各種策略配置。
  4. 外掛熱插拔,易擴充套件
  5. 支援叢集部署,支援A/B Test

總結一下:

  1. 效能
    Nginx+Lua形式必然是高於Java語言實現的閘道器的,Java技術棧裡面Zuul1.0是基於Servlet實現的,剩下都是基於webflux實現,效能是高於基於Servlet實現的。在效能方面我覺得選擇閘道器可能不算那麼重要,多加幾臺機器就可以搞定。
  2. 可維護性和擴充套件性
    Nginx+Lua這個組合掌握的人不算多,如果團隊有大神,大佬們就隨意了,當沒看到這段話,對於一般團隊來說的話,選擇自己團隊擅長的語言更重要,所以我選擇了Java技術棧下的閘道器。Java技術棧下的3種閘道器,對於Zuul和Spring Cloud Getway需要或多或少要搞一些整合和配置頁面來維護,但是對於Soul我就無腦看看文章,需要哪個搬哪個好了,尤其是可以無腦對接Dubbo美滋滋,此外Soul2.0以後版本可以擺脫ZK,在我心裡再無詬病,我就喜歡無腦操作。
  3. 高可用
    對於閘道器高可用基本都是統一的策略都是採用多機器部署的方式,前面掛一個負載,對於而外需要用的一些元件大家注意一下。

結束

歡迎大家點點關注,點點贊,感謝!

相關文章