整合一套高性能網關Kong
前言
相信大家對Api網關都比較的熟悉,我們之前的文章也介紹過ASP.NET Core的網關Ocelot,也介紹過Spring Cloud Gateway。說到網關的主要功能,其實總結起來就兩個字”統一”,無論是作為應用的入口、認證授權、熔斷限流等等主要都是為了統一的地方做一些事情。今天我們介紹一款性能更高的網關Kong,相對於Ocelot或Gateway這些類型的網關來說,Kong的優勢是具有更高的性能,主要因為Kong是基於Nginx+Lua為核心的,接下來我們就詳細介紹一下。
概念介紹
在使用Kong之前我們先來大致的介紹一下Kong是什麼,Kong是基於OpenResty的開源網關。而OpenResty是基於Nginx與Lua的高性能Web平台。經常使用Nginx的同學們都知道,如果修改了Nginx的配置是需要重啟Nginx的。而OpenResty讓Nginx具備了動態編程的能力,使得Nginx成為了一個應用伺服器軟體,Kong正是基於OpenResty的,Nginx的性能不必多說,所以Kong可以理解為運行在Nginx上的高性能網關,在學習的過程中我們可以類比著Nginx進行了解。
Kong
說了這麼多接下來我們大致介紹一下Kong自學三件套
- 官方Github地址://github.com/Kong/kong
- 官方網站地址://konghq.com/
- 開源版官方文檔地址://docs.konghq.com/gateway-oss/為什麼這裡要說開源版呢,相信大家已經猜到了,因為它還有企業版、SaaS版、Ingress、Mesh等等,即有常規部署方式也有基於K8S和Mesh的方式,這裡我們就不過多介紹了。
Kong有一點做的還是比較好的,無論是GitHub還是官方文檔介紹的都比較詳細,而且比較通俗易懂,這裡我們就不過多的介紹了,有興趣的同學可以自行了解一下。介紹完了自學三件套之後,接下來我們了解一下搭建一套Kong的幾個組成部分,總結起來就是三個Kong服務、Kong依賴的存儲、Kong可視化介面,下面我們大致的介紹一下。
- 首先是Kong服務,一套可以正常工作的Kong會包含兩個對外提供服務的埠,一個是網關常規使用的埠,即對外提供訪問的入口。另一個則是管理Kong的Admin埠,比如對Kong管理服務的增刪改查以及Kong常用的Plugin管理以及一些常規的配置等,Kong的插件非常的豐富,基本上可以到達常規的一些操作比如限流、認證授權、鏈路跟蹤、監控等都有而且形式非常的豐富。
- 其次是Kong存儲服務,因為在Kong上配置的轉發服務、插件、環境變數、認證等相關的資訊都是需要存儲的,但是外部存儲不是必須的,Kong可以將這些資訊存儲到進程內的快取中,但是重啟Kong之後這些配置將會丟失,因此在正常的使用過程中我們總會給他提供一個外部資料庫來存儲這些資訊。可供Kong使用的存儲資料庫也有好幾個選擇分別是Mysql、MongoDB、Postgresql等。本次演示我們使用的是Postgresql,也是官方推薦的方式。
- 最後是Kong的可視化UI,當然這個不是必須的。Kong提供了Admin管理介面的形式對服務和Plugin查看、新增、修改、刪除等操作,但是有一個可視化的管理介面,無疑讓有些操作變得更加簡單清晰,而且這些可視化系統正式基於Kong的Admin介面開發的。可供選擇的可視化UI也比較多,比較出名的有Konga、kong-ui、kong-admin-ui。本次演示我們選擇的是Konga,也是推薦使用的最多的一個。
Konga
Konga並非Kong官方出品的可視化UI,但是它是最流行的一個,也是使用最多的一個,目前最新版本是v0.6.3。Konga是基於Nodejs開發的,它的Github地址是//github.com/pantsel/konga,同樣的Konga的GitHub文檔上介紹的也非常的詳細。它的部署方式有兩種,一個是直接克隆GitHub上的倉庫上的程式碼通過npm的方式運行,另一種則是使用docker的方式部署。兩種方式都非常的簡單,本次我們選擇docker的方式。
環境搭建
關於Kong的搭建,官方網站給出了好幾種部署方式可以基於Docker或K8S,也可以在Liunx作業系統Centos、Ubuntu、RHEL等都支援,目前最穩定版本為2.3.x,這些在官方文檔上講解的非常詳細非常易懂,具體可參閱官方文檔//konghq.com/install/。如果想能快速的搭建起一套Kong+Postgresql+Konga
的環境,docker-compose無疑是一個比較好的選擇,接下來我們將演示用過這種方式快速搭建起一條完整的Kong環境。
Kong官方GitHub有專門的docker-kong倉庫地址為//github.com/Kong/docker-kong,也已將這個倉庫Clone下來,找到compose文件運行。但是我們這裡還要整合可視化介面Konga,Konga並非官方出品,所以我要要修改一下compose文件整合進去Konga,完整的呈現如下所示
version: '3.3'
#創建kong_data卷
volumes:
kong_data: {}
#創建kong-net網路
networks:
kong-net:
external: false
services:
#資料庫運行完成之後需要執行kong進行初始化操作
kong-migrations:
image: "${KONG_DOCKER_TAG:-kong:latest}"
command: kong migrations bootstrap
depends_on:
- db
environment:
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
deploy:
restart_policy:
condition: on-failure
#遷移過程依賴db
kong-migrations-up:
image: "${KONG_DOCKER_TAG:-kong:latest}"
command: kong migrations up && kong migrations finish
depends_on:
- db
environment:
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
deploy:
restart_policy:
condition: on-failure
# kong服務
kong:
image: "${KONG_DOCKER_TAG:-kong:latest}"
user: "${KONG_USER:-kong}"
depends_on:
- db
environment:
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: '0.0.0.0:8001'
KONG_CASSANDRA_CONTACT_POINTS: db
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
#kong的埠,非https使用8000和8001
ports:
- "8000:8000/tcp"
- "8001:8001/tcp"
- "8443:8443/tcp"
- "8444:8444/tcp"
#健康檢查
healthcheck:
test: ["CMD", "kong", "health"]
interval: 10s
timeout: 10s
retries: 10
restart: on-failure
deploy:
restart_policy:
condition: on-failure
#konga可視化介面
konga:
image: pantsel/konga
networks:
- kong-net
depends_on:
- db
ports:
- "1337:1337/tcp"
environment:
TOKEN_SECRET: konga
DB_ADAPTER: postgres
DB_HOST: db
DB_PORT: 5432
DB_USER: kong
DB_PASSWORD: kong
DB_DATABASE: kong
restart: on-failure
deploy:
restart_policy:
condition: on-failure
# postgres資料庫
db:
image: postgres:9.6
environment:
POSTGRES_DB: ${KONG_PG_DATABASE:-kong}
POSTGRES_USER: ${KONG_PG_USER:-kong}
POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
healthcheck:
test: ["CMD", "pg_isready", "-U", "${KONG_PG_USER:-kong}"]
interval: 30s
timeout: 30s
retries: 3
restart: on-failure
deploy:
restart_policy:
condition: on-failure
stdin_open: true
tty: true
ports:
- 5432:5432
networks:
- kong-net
volumes:
- kong_data:/var/lib/postgresql/data
# 用文件統一管理資料庫密碼
secrets:
kong_postgres_password:
file: ./POSTGRES_PASSWORD
通過docker-compose直接運行上面的yaml文件,便可以直接運行一套完整的kong項目,這裡在強調一下上面說過GitHub上有官方專門提供的docker-kong倉庫,直接Clone便可以直接得到運行Kong的yaml,但是本示例我們加入了Konga,如果需要可直接下載我修改後的包[點擊下載👈]下載完成之後進入docker-compose.yml
所在的文件夾,執行docker-compose up -d
指令,首次的話會下載依賴的鏡像文件可能稍微慢一點,出現如下介面的時候說明正常運行完成

{
"message": "no Route matched with those values"
}
因為我們沒有配置任何路由規則,所以會提升匹配不到路由。然後我們在瀏覽器打開konga的地址//localhost:1337/出現如下介面,則表示kong和konga運行成功

操作使用
通過上面的操作我們已經成功運行起來了Kong+Konga+Postgresql
的運行環境,然後我們就可以使用這套網關完成服務的轉發相關的操作,常用的方式有兩種,一種是通過Konga直接配置,另一種則是直接通過Kong服務的8001
埠訪問管理的restful介面進行操作,當然Konga也是基於這套介面來操作的,接下來我們就來大致演示一下使用這兩種方式完成相關操作。
通過Konga介面配置
打開Konga之後首次會讓註冊登錄資訊,註冊完成之後會讓完成Konga的配置連接操作,主要就是配置Kong的管理介面




首先配置Upstreams,由於kong本質處理請求還是通過nginx進行的,所以概念可以直接和nginx類比過來,其實就是是類似配置一個轉發操作,這個操作既可以是一個服務地址,也可以是一組服務集合








那麼Host就是是Upstream的名稱或真實的訪問目標地址名稱


ADD ROUTE
會彈出添加Route資訊的彈窗,主要配置Name、Host Paths Strip Path具體含義可看截圖

OrderService
服務里獲取訂單詳情的地址為//localhost:5001/order/get/1
,我們在通過網關訪問OrderService的時候地址是//localhost:8000/orderservice/order/get/1
,這種情況Path里的orderservice對我來說只是為了能訪問到OrderService的一個路徑標識,真實服務OrderService的時候並不需要,這個時候我就可以設置Strip Path的值為true
,這樣在轉發地址的時候就不會在Url上帶上orderservice這個標識了。到這裡,關於通過Konga配置的常用操作介紹的就差不多了,截圖上也標註了常用欄位的含義,想更詳細的了解還需要自己搭建一套Konga實操一下。
通過Kong的Admin介面配置
上面我們介紹了通過Konga的方式配置Kong的服務,我們開始的時候也說過,Konga也是通過Kong Admin API的介面完成對服務的增刪改查的操作的,Kong Admin API是Kong自帶的管理介面,通過這些介面我們可以通過更原生的方式去操作Kong。而且如果你通過Konga配置的時候不太了解哪些欄位是必須的,或者需要理解每個欄位詳細代表的含義,這時候就可以通過原生的介面了解,這樣有助於更深刻的了解。Admin API的官方文檔地址位於//docs.konghq.com/gateway-oss/2.3.x/admin-api/文檔介紹的非常的詳細,接下來我們就大致的介紹Admin API的一些常規操作。
- 默認情況Admin API的監聽埠是8001,如果是https的話默認為8444
- API可接收的內容格式即ContentType為application/json、application/x-www-form-urlencoded、multipart/form-data
- Kong Admin API是標準的Restful風格的介面,這對於我們操作來說非常的便捷
由於Admin API官方文檔介紹的非常詳細了,這裡咱們就不一一的介紹了,咱們這裡簡單的介紹一下有代表性的介面和一些注意相關的操作。強烈建議,學習Kong的話一定要看這個文檔,這樣的話能解決很多的困惑。首先介紹Service的List的介面,這個介面是返回註冊在Kong上的所有Service
- 請求方式是
curl //localhost:8001/services
- 成功的狀態碼為
HTTP 200 OK
- 返回的json格式代表的含義,文檔中介紹的也非常詳細
{
"data": [{
"id": "a5fb8d9b-a99d-40e9-9d35-72d42a62d83a",
"created_at": 1422386534,
"updated_at": 1422386534,
"name": "my-service",
"retries": 5,
"protocol": "http",
"host": "example.com",
"port": 80,
"path": "/some_api",
"connect_timeout": 60000,
"write_timeout": 60000,
"read_timeout": 60000,
"tags": ["user-level", "low-priority"],
"client_certificate": {"id":"51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"},
"tls_verify": true,
"tls_verify_depth": null,
"ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"]
}],
"next": "//localhost:8001/services?offset=6378122c-a0a1-438d-a5c6-efabae9fb969"
}
data為數據結果,next是下一批數據查詢的地址。這一點做得還是考慮的比較周全的,如果Service比較多的話,一次性返回不是一個明智的操作,通過判斷next的方式可以知道是否存在分頁的情況,根據判斷狀態碼可以知道請求是否成功。
其次Service還有一個檢索介面,它主要用於返回指定的Service資訊,它的請求方式是curl //localhost:8001/services/{service name or id}
,如果返回的狀態碼為404
則說明服務沒有被註冊過,如果服務存在則狀態碼為200
並返回服務詳情的json。
還有一個比較實用的介面是Update Or Create Service
翻譯過來就是修改或創建,即如果Service存在則執行更新操作,如果不存在則直接創建一個Service。試著想一下,如果不存在這個介面,我們每次註冊Service之前還要調用一下檢索介面判斷一下Service是否被註冊過。
請求方式是curl -X PUT -H "Content-Type: application/json" -d '{}' "//localhost:8001/services/{service name or id}"
它的請求數據格式和Add的是一樣的只是請求方式是PUT
它的數據格式是
{
"id": "9748f662-7711-4a90-8186-dc02f10eb0f5",
"created_at": 1422386534,
"updated_at": 1422386534,
"name": "my-service",
"retries": 5,
"protocol": "http",
"host": "example.com",
"port": 80,
"path": "/some_api",
"connect_timeout": 60000,
"write_timeout": 60000,
"read_timeout": 60000,
"tags": ["user-level", "low-priority"],
"client_certificate": {"id":"4e3ad2e4-0bc4-4638-8e34-c84a417ba39b"},
"tls_verify": true,
"tls_verify_depth": null,
"ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"]
}'
它返回的結果是HTTP 201 Created or HTTP 200 OK
這裡需要特別注意的是Add相關的介面返回的Http是HTTP 201 Created
我們就通過關於Service的操作,大致介紹一下關於Admin API的大致操作方式,關於每一個Service、Route、Upstream、Target的操作都有完整的增刪改查介面,咱們上面介紹的是除了這些之外實用操作的介面。這裡還需要注意的是有些操作是有關聯關係的,比如Service和Route的操作,Upstream和Target的操作,因此在實際通過介面開發的過程中要注意對Service的Id或Upstream的Id的保存。
因為Kong對註冊中心這些比如Consul、Eureka、Nacos這種支援的並不是很完善,雖然Kong支援自己編寫Lua腳本的方式完成這些操作,但是這些編寫成本還是比較高的,所以這個時候Admin API就顯得格外的實用。
總結
本次我們主要講解了對Kong的大致入門操作,相信很多同學都聽說過或者用過它,我個人覺得Kong這種級別的組件很多時候能了解它的大致場景和結構並能搭建出來一套可運行的環境,那麼入門就已經完成一半了。我覺得Kong做的比較好的一點是,它的學習文檔和GitHub倉庫上的一些操作都非常的完整而且很詳細。我每次寫這種類型的文章其實初衷都非常的簡單,就是能讓對這些東西有興趣的同學,能通過這篇文章入門,算是能有一個好的開始吧。
