當前微服務網關的技術選型不少。常見的有springcloud系的zuul1,gateway;也能夠選擇nginx+lua方案;或者直接使用UI集成度較高的Kong。java
本文記述瞭如何使用docker安裝kong與konga(一個開源的Kong管理UI項目),以及它們的簡單使用和一些注意事項。nginx
官方文檔:https://docs.konghq.com/install/docker/
git
2020/07/03 kong目前的最新版本2.0.4,在作websocket轉發時,與tomcat版本9.0.29有衝突,會致使websocket沒法正常轉發。所以這裏咱們選擇安裝kong的一個稍微低一點的版本
2.0.0
。
# 若是不指定subnet,建立的network默認使用172.17網段,可能會與實際網段發生衝突 docker network create --subnet=12.10.10.0/24 kong-net # 拉取postgres:9.6做爲kong的數據庫 docker run -d --name kong-database \ --network=kong-net \ -p 5432:5432 \ -e "POSTGRES_USER=kong" \ -e "POSTGRES_DB=kong" \ -e "POSTGRES_PASSWORD=kong" \ postgres:9.6 # 拉取kong:2.0.0並生成初期數據 docker run --rm \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ kong:2.0.0 kong migrations bootstrap # 啓動kong docker run -d --name kong \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ -p 8000:8000 \ -p 8443:8443 \ -p 127.0.0.1:8001:8001 \ -p 127.0.0.1:8444:8444 \ kong:2.0.0 # 啓動後在宿主機訪問8000與8001端口 curl http://localhost:8000 curl http://localhost:8001
注意,kong的四個端口做用:github
- 8000與8443分別用於對http和https的代理訪問;
- 8001與8444分別是http與https的管理API訪問端口,由於管理API不宜對外暴露,因此在掛載端口時,明確了
127.0.0.1
,即只有宿主機本地可以訪問。
konga安裝直接默認最新版本(目前是0.14.9)。web
# 拉取pantsel/konga,並建立數據庫konga_db。 # 注意這裏直接使用剛剛爲了kong建立的PG數據庫實例,並使用kong的DB用戶, # 注意這裏postgresql鏈接的寫法: # postgresql://<用戶>:<密碼>@<PG_Host>:<PG_Port>/<database> docker run --rm \ --network=kong-net \ pantsel/konga -c prepare -a postgres -u postgresql://kong:kong@kong-database:5432/konga_db # 啓動konga docker run -p 1337:1337 \ --network=kong-net \ -e "DB_ADAPTER=postgres" \ -e "DB_HOST=kong-database" \ -e "DB_USER=kong" \ -e "DB_PASSWORD=kong" \ -e "DB_DATABASE=konga_db" \ -e "KONGA_HOOK_TIMEOUT=120000" \ -e "NODE_ENV=production" \ --name konga \ pantsel/konga
konga從命令行啓動後不會退出,但docker容器已經正常啓動。建議後面經過
portainer
來重啓該容器。(portainer是一個開源的docker管理工具,自己直接拉取docker運行便可。)
觀察docker容器情況,確認kong-database
、kong
、konga
三個容器所有成功啓動後,訪問地址:http://localhost:1337
。正則表達式
首次訪問會讓你建立konga的管理員帳戶,而後登陸,而後建立到kong管理API的鏈接,過程以下:spring
http://kong:8001/
)注意上面第三步,建立到kong管理API的鏈接時,由於前面啓動kong時,8001端口只掛載在12.0.0.1:8001
上,所以只有宿主機本身能夠訪問。這裏在konga容器內訪問kong時,就必須經過網絡kong-net
中的容器ip或hostname訪問。所以這裏填寫的是kong容器的name:kong
,而不是宿主機IP。
此時konga的界面仍是比較簡陋的,功能也很少。dashbord只能看到一些整體的統計信息,看不到具體每一個目標服務的訪問量。sql
若是須要添加其餘功能,須要經過PLUGINS去一個一個添加,具體還沒有研究。docker
但動態添加路由規則是徹底沒有問題的。這裏主要介紹如何添加路由規則。數據庫
kong添加路由規則主要分爲兩步:
經過左側導航菜單SERVICES
,添加目標服務ADD NEW SERVICE
,通常配置項目以下:
/
注意Path不要空着,沒有指定Path就填上
/
表示服務根目錄。
其餘項目通常保持默認便可。
經過左側導航菜單SERVICES
,點擊一個目標服務,選擇它的Routes
,並點擊ADD ROUTE
,配置以下:
POST
,GET
等。屬性:值
填入便可,注意回車。例如:Connection: keep-alive
。注意:
- Hosts,Paths,Methods三者最少須要配置一個。
- 大部分狀況下,咱們都是根據Path來作轉發的過濾條件的,所以不一樣目標系統若是某些資源訪問Path相同的話,會致使不一樣目標服務的路由規則衝突。
關於Path衝突,建議以下:
- 儘可能確保不一樣的目標服務具備各自統一的資源訪問根目錄。即每一個目標服務都有本身統一且惟一的Path前綴。如,某個目標服務的Path都是
/service1/*
,靜態資源用/service1/static/*
,API用/service1/api/*
等等。- 沒有統一訪問根目錄的目標服務,儘可能保證各自的路徑知足不一樣的正則表達式。好比Path的中間某一層統一爲能識別具體服務的字符串。如,某個目標服務的Path都知足
/*/service2/*
,靜態資源用/static/service2/*
,API用/api/service2/*
等等。- 前面兩點都不能知足的話,考慮加入其餘過濾條件(Hosts,Headers等),例如,網關有多個域名,當請求用域名1訪問時,路由到目標服務1,用域名2訪問時,路由到目標服務2。
kong是天生支持websocket轉發的,關於這一點,能夠參考官網的說明:https://docs.konghq.com/2.0.x/proxy/#proxy-websocket-traffic
但當kong位於客戶端與服務端之間時,kong的某些版本與服務器的版本可能會有衝突,致使websocket轉發發生異常。
例如,目前kong的最新版本(2.0.4)做爲網關,若是目標服務是tomcat的9.0.29版本,那麼會發生如下現象:
Error during WebSocket handshake: 'Upgrade' header is missing
錯誤。java.io.EOFException
異常,致使鏈接被關閉。具體緣由在kong的issue #5714 (https://github.com/Kong/kong/issues/5714
) 中有討論,該issue已被關閉但實際上問題並未解決。。。卻是其中一個回答提到,若是將kong版本回退到2.0.0
則該問題不會發生。