[前言]:
Kong是一個雲原生,高效,可擴展的分布式 API 網關。 自 2015 年在 github 開源后,廣泛受到關注,目前已收獲 1.68w+ 的 star,其核心價值在於高性能和可擴展性。
為什么需要 API 網關(more)
在微服務架構之下,服務被拆的非常零散,降低了耦合度的同時也給服務的統一管理增加了難度。如上圖左所示,在舊的服務治理體系之下,鑒權,限流,日志,監控等通用功能需要在每個服務中單獨實現,這使得系統維護者沒有一個全局的視圖來統一管理這些功能。API 網關致力於解決的問題便是為微服務納管這些通用的功能,在此基礎上提高系統的可擴展性。如右圖所示,微服務搭配上 API 網關,可以使得服務本身更專注於自己的領域,很好地對服務調用者和服務提供者做了隔離。
使用API網關帶來一下幾個好處:
- 統一API入口
- 隔離后端
- 認證鑒權流控
- 負載均衡
- 降低后端開發對API安全性的考慮
其實無論是否是微服務的架構,只要用到了認證鑒權流控功能,我覺得都應該使用API網關,這將大大減低后端開發的成本和速度,未來擴張也方便。
目前各大雲廠商都可用了商用的API網關,例如阿里雲,功能強大,性能穩定,如果應用於雲上的生產環境,也可以考慮。
當然開源社區中也提供幾種開源的方案
名稱 | 說明 |
---|---|
Tyk | Tyk是一個開放源碼的API網關,它是快速、可擴展和現代的。Tyk提供了一個API管理平台,其中包括API網關、API分析、開發人員門戶和API管理面板。Try 是一個基於Go實現的網關服務。 |
Kong | Kong是一個可擴展的開放源碼API Layer(也稱為API網關或API中間件)。Kong 在任何RESTful API的前面運行,通過插件擴展,它提供了超越核心平台的額外功能和服務。 |
Orange | Orange和Kong類似也是基於OpenResty的一個API網關程序,是由國人開發的。 |
Zuul | Zuul是一種提供動態路由、監視、彈性、安全性等功能的邊緣服務。Zuul是Netflix出品的一個基於JVM路由和服務端的負載均衡器。 |
apiaxle | Nodejs 實現的一個 API 網關。 |
api-umbrella | Ruby 實現的一個 API 網關。 |
kong的概念
Kong是一個在Nginx中運行的Lua應用程序,並且通過lua-nginx模塊實現。Kong不是用這個模塊編譯Nginx,而是與OpenResty一起發布,OpenResty已經包含了lua-nginx-module
OpenResty 也不是 Nginx的分支,而是一組擴展其功能的模塊。
Kong是一個可擴展的開源API網關,運作在RESTfull API之前,提供統一的入口,並且通過插件的形式進行擴展,插件提供了平台核心功能意外的功能和服務,例如鑒權、流控等等。
Kong 是 Mashape 開源的高性能高可用 API 網關和 API 服務管理層,一款基於 Nginx_Lua 模塊寫的高可用服務網關,由於 Kong 是基於 Nginx 的,所以它是一個可擴展的服務,只需要添加多台服務器就可以配置成一個集群。通過前置的負載均衡配置把請求均勻地分發到各個 Server,來應對大批量的網絡請求。
為什么使用Kong
SpringCloud 玩家肯定都聽說過 Zuul 這個路由組件,包括 Zuul2 和 Springcloud Gateway 等框架,在國內的知名度都不低。沒錯,我稱呼這些為組件 Or 框架,而 Kong 則更襯的上產品這個詞。在此我們可以簡單對比下 Zuul 和 Kong。
舉例而言,如果選擇使用 Zuul,當需要為應用添加限流功能,由於 Zuul 只提供了基本的路由功能,開發者需要自己研發 Zuul Filter,可能你覺得一個功能還並不麻煩,但如果在此基礎上對 Zuul 提出更多的要求,很遺憾,Zuul 使用者需要自行承擔這些復雜性。而對於 Kong 來說,限流功能就是一個插件,只需要簡單的配置,即可開箱即用。
Kong 的插件機制是其高可擴展性的根源,Kong 可以很方便地為路由和服務提供各種插件,網關所需要的基本特性,Kong 都如數支持:
- 雲原生: 與平台無關,Kong可以從裸機運行到Kubernetes
- 動態路由:Kong 的背后是 OpenResty+Lua,所以從 OpenResty 繼承了動態路由的特性
- 熔斷
- 健康檢查
- 日志: 可以記錄通過 Kong 的 HTTP,TCP,UDP 請求和響應。
- 鑒權: 權限控制,IP 黑白名單,同樣是 OpenResty 的特性
- SSL: Setup a Specific SSL Certificate for an underlying service or API.
- 監控: Kong 提供了實時監控插件
- 認證: 如數支持 HMAC, JWT, Basic, OAuth2.0 等常用協議
- 限流
- REST API: 通過 Rest API 進行配置管理,從繁瑣的配置文件中解放
- 可用性: 天然支持分布式
- 高性能: 背靠非阻塞通信的 nginx,性能自不用說
- 插件機制: 提供眾多開箱即用的插件,且有易於擴展的自定義插件接口,用戶可以使用 Lua 自行開發插件
上面這些特性中,反復提及了 Kong 背后的 OpenResty,實際上,使用 Kong 之后,Nginx 可以完全摒棄,Kong 的功能是 Nginx 的父集。
而 Zuul 除了基礎的路由特性以及其本身和 SpringCloud 結合較為緊密之外,並無任何優勢。
Kong 的管理方式
Kong 簡單易用的背后,便是其所有的操作都是基於 HTTP Restful API 來進行的。
其中 8000/8443 分別是 Http 和 Https 的轉發端口,等價於 Nginx 默認的 80 端口,而 8001 端口便是默認的管理端口,我們可以通過 HTTP Restful API 來動態管理 Kong 的配置。
例:一個典型的 Nginx 配置
upstream helloUpstream {
server localhost:3000 weight=100;
}
server {
listen 80;
location /hello {
proxy_pass http://helloUpstream;
}
}
如上這個簡單的 Nginx 配置,便可以轉換為如下的 Http 請求。
對應的 Kong 配置:
# 配置 upstream
curl -X POST http://localhost:8001/upstreams --data "name=helloUpstream"
# 配置 target
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3000" --data "weight=100"
# 配置 service
curl -X POST http://localhost:8001/services --data "name=hello" --data "host=helloUpstream"
# 配置 route
curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id=8695cc65-16c1-43b1-95a1-5d30d0a50409"
這一切都是動態的,無需手動 reload nginx.conf。
從上面的配置及字面解釋大概能夠推測出他們的職責:upstream,target,service,route
,他們便是 Kong 最最核心的四個對象
upstream 是對上游服務器的抽象;
target 代表了一個物理服務,是 ip + port 的抽象;
service 是抽象層面的服務,他可以直接映射到一個物理服務(host 指向 ip + port),也可以指向一個upstream來做到負載均衡;
route 是路由的抽象,他負責將實際的 request 映射到 service。
他們的關系如下:
- upstream 和 target :1 對 n
- service 和 upstream :1 對 1 或 1 對 0 (service 也可以直接指向具體的 target,相當於不做負載均衡)
- service 和 route:1 對 n
高可擴展性的背后—插件機制
Kong 的另一大特色便是其插件機制,這也是我認為的 Kong 最優雅的一個設計。
文章開始時我們便提到一點,微服務架構中,網關應當承擔所有服務共同需要的那部分功能,這一節我們便來介紹下,Kong 如何添加 jwt 插件,限流插件。
插件(Plugins)裝在哪兒?對於部分插件,可能是全局的,影響范圍是整個 Kong 服務;大多數插件都是裝在 service 或者 route 之上。這使得插件的影響范圍非常靈活,我們可能只需要對核心接口進行限流控制,只需要對部分接口進行權限控制,這時候,對特定的 service 和 route 進行定向的配置即可
為 hello 服務添加50次/秒的限流
curl -X POST http://localhost:8001/services/hello/plugins \
--data "name=rate-limiting" \
--data "config.second=50"
為 hello 服務添加 jwt 插件
curl -X POST http://localhost:8001/services/login/plugins \
--data "name=jwt"
同理,插件也可以安裝在 route 之上
curl -X POST http://localhost:8001/routes/{routeId}/plugins \
--data "name=rate-limiting" \
--data "config.second=50"
curl -X POST http://localhost:8001/routes/{routeId}/plugins \
--data "name=jwt"
在官方文檔中,我們可以獲取全部的插件 https://konghq.com/plugins/,部分插件需要收費的企業版才可使用。
本文參考:
https://mp.weixin.qq.com/s/CWGy6cwy6QGLvwByurEGbw
https://www.jianshu.com/nb/27758849
[sleepy↓]