kong 集群將使得系統通過增加更多機器,從而實現水平擴展,承接更多的請求流量。它們將共享同樣的配置且使用同一個數據庫。kong 集群中的的所有節點都連接同一個數據庫。
你需要在 kong 集群的上一層架設一個負載均衡的代理服務器,以便請求能夠平均分散轉發到 kong 的各個節點上。
目錄
- 一.kong 集群能做什么和不能做什么
- 二.單節點 kong 集群
- 三.多節點 kong 集群
- 四.什么是緩存
- 五.如何配置數據庫緩存
- 1.db_update_frequency
- 2.db_update_propagation
- 3.db_cache_ttl
- 4.當使用 Cassandra 數據庫
- 六.通過Admin api 操作緩存
- 1.檢查一個緩存值
- 2.清理一個緩存值
- 3.清理一個節點的緩存
- 七.集群搭建
一.kong 集群能做什么和不能做什么
擁有Kong群集並不意味着客戶端流量將在開箱即用的Kong節點中實現負載平衡,仍然需要在Kong節點前面使用負載平衡器來分配流量。相反,Kong群集意味着這些節點將共享相同的配置。
出於性能原因,Kong在代理請求時避免數據庫連接,並將數據庫的內容緩存到內存中。cached實體包括services,routes,consumers,plugins,credentials等...由於這些值在內存中,因此通過其中一個節點的Admin API進行的任何更改都需要傳播到其他節點。
本文檔將介紹,如何使得這些本地緩存失效,並且如何配置 kong 集群節點,以便支持更多的使用場景,從而在性能和數據強一致性兩方面做出平衡的選擇。
二.單節點kong 集群
只有一個 kong 節點連接數據庫(Cassandra或PostgreSQL)的單節點 kong 集群,任何通過 Admin api 的更改,都會立即全局生效。比如:
假設只有一個kong單節點A ,如果我們刪除一個已經注冊的Service:
$ curl -X DELETE http://127.0.0.1:8001/services/test-service
隨后任何關於 kong節點A 請求都將會返回 “404 Not Found”,因為該節點已經在本地刪除中清除了緩存。
$ curl -i http://127.0.0.1:8000/test-service
三.多節點kong 集群
在一個多節點 kong 集群中,當我們通過A 節點的Admin api刪除某條信息,其他節點雖然都連接同一個數據庫,但由於本地緩存存在,所以並不會立即生效。雖然API 不再存儲在數據庫中(通過A 節點的Admin api 刪除的),但它仍然存在 B以及其他節點的內存中。
所有節點將會周期性執行后台同步任務,同步其他節點觸發的變化。該同步任務執行頻率可以通過配置下面的配置項:
◦ db_update_frequency (默認: 5 秒)
每 db_update_frequency 秒,所有 kong 節點將從數據庫中拉取所有更新,如果有同步到更新變化,將清理本地相關緩存。
如果我們通過 kong-A 節點刪除一個 API,這個更新變化將不會立即在 B 節點生效,直到 B 節點下一次從數據庫拉取變更,這將會是在db_update_frequency 秒后才會發生(也有可能會更早)。
這個過程將會使 kong 集群最終保持一致性。
四.什么是緩存
所有核心實體(如服務,路由,插件,消費者,憑證)都由Kong存儲在內存中,緩存失效則依賴后台任務同步更新。此外,kong 也會緩存數據庫遺漏(數據庫中有的數據,但本地不存在的)。這意味着如果你配置一個沒有插件的服務,Kong會緩存這些信息。例:
在節點A上,我們添加一個Service和一個Route
# node A $ curl -X POST http://127.0.0.1:8001/services \ --data "name=example-service" \ --data "url=http://example.com" $ curl -X POST http://127.0.0.1:8001/services/example-service/routes \ --data "paths[]=/example"
(請注意,我們使用/services/example-service/routes作為快捷方式:也可以使用/routes endpoint代替,但我們需要將service_id作為參數傳遞給新服務的UUID。)
對節點A和節點B的代理端口的請求將緩存該服務,並且沒有在其上配置插件:
# node A $ curl http://127.0.0.1:8000/example HTTP 200 OK ... # node B $ curl http://127.0.0.2:8000/example HTTP 200 OK ...
現在,假設我們通過節點A的管理API向該服務添加一個插件:
# node A $ curl -X POST http://127.0.0.1:8001/services/example-service/plugins \ --data "name=example-plugin"
由於此請求是通過節點A的Admin API發出的,因此節點A將在本地使其緩存無效,並在隨后的請求中檢測到此API配置了插件。
但是,kong-B 節點還沒有執行數據庫同步更新緩存任務,本地緩存的API信息並沒有配置插件,直到 kong-B 節點執行數據庫同步操作之后,API新增插件的功能才會生效。
結論:所有CRUD操作都會觸發緩存失效。創建(POST,PUT)將使緩存的數據庫未命中失效,更新/刪除(PATCH,DELETE)將使緩存的數據庫命中無效。
五.怎樣配置DB緩存
可以在Kong配置文件中配置3個屬性,其中最重要的一個屬性是db_update_frequency,它決定了Kong節點在性能與一致性之間的權衡。
kong 已經提供了默認的配置,為了讓你權衡集群性能和數據一致性兩個方面,避免意外的結果。你可以按照下面的配置步驟,改變配置的值,從而確保性能和數據一致性能夠被接受。
- 1.db_update_frequency (default: 5s)
該配置決定 kong 節點從數據庫拉取緩存無效事件,同步任務執行的頻率。一個更小的值意味着同步任務將會更頻繁的執行,kong 節點的緩存數據將保持和數據庫更強的一致性。一個更大的值,意味着你的 kong 節點花更少的時間去處理同步任務,從而更加將更多資源集中去處理請求。
Note:變更將會在db_update_frequency 秒后在整個集群節點中生效。
- 2.db_update_propagation (default: 0s)
如果你的數據庫也是集群的並且最終一致性的(比如:Cassandra),你必須配置該值。它將確保db_update_propagation秒后,數據庫節點間的變化在整個數據庫集群中所有節點生效。當配置了該值,kong 節點從同步任務中接收無效事件,清除本地緩存將會延遲 db_update_propagation 秒。
如果一個 kong 節點連接到最終一致性數據庫上,且沒有延遲事件需要處理,它可能會清除緩存,然后把沒有更新的值再次緩存起來。(因為這個改變還沒有傳播到數據庫集群的每一個節點,注釋:數據庫一致性還沒有在數據庫集群中達到一致,此時kong緩存到期了,但是沒有更新到變化事件,此時會把沒有更新的值再次緩存起來,導致kong也出現不一致,即便kong執行了同步任務。)。
你應該配置該值,通過評估數據庫集群發生變更后,最終達到一致性所需要的時間。(確保數據庫一致之后,才去執行 kong 同步任務處理變更事件,從而達到kong 數據一致性)
Note:當配置了該配置項,數據變更傳播到 kong 集群的最大時間是 db_update_frequency + db_update_propagation 秒。
- 3.db_cache_ttl (default: 3600s)
該配置項的時間(單位秒)是 kong 緩存數據庫實體的時間(包括緩存命中或者穿透),該存活時間是一種保護措施,以防 kong 節點漏掉處理緩存無效事件,避免舊數據長時間沒有被清理。當緩存生存時間到了,緩存值將會被清理掉,下一次將會從數據庫讀取數據並再次緩存起來。
- 4.當使用 Cassandra 數據庫
如果使用 Cassandra 作為 kong 的數據庫,你必須配置 db_update_propagation 為一個非零值。由於 Cassandra 本身是最終一致性數據庫,這將確保 kong 節點不會過早地使本地緩存失效,僅僅當再次獲取到一個不是最新值的時候。如果你使用了 Cassandra 但你沒有配置該值時,kong 將會輸出一條警告日志。
此外,你可以配置 cassandra_consistency 的值為:比如 QUORUM 或者 LOCAL_QUORUM,確保被kong 緩存的值是數據庫中最新的。
六.通過Admin Api操作緩存
由於某些原因,你希望通過 kong 查看緩存的值,或者手動清理緩存(當緩存被命中或者丟失),你可以通過使用 Admin api /cache 接口進行管理。
查看緩存值-Inspect a cached value
Endpoint
GET /cache/{cache_key}
Response
返回值 當 key 被有效緩存: HTTP 200 OK ... { ... } 否則: HTTP 404 Not Found
注意:檢索由Kong緩存的每個實體的cache_key目前是一個未公開的過程。 Admin API的未來版本將使此過程更加簡單。
清除緩存值-Purge a cached value
Endpoint
DELETE /cache/{cache_key}
Response
HTTP 204 No Content ...
清除節點緩存-Purge a node's cache
Endpoint
DELETE /cache
Response
HTTP 204 No Content
注意:請謹慎在生產運行節點上使用此接口。如果節點接收到大量流量,同時清除其緩存將觸發對數據庫的許多請求,並可能導致DB請求堆積現象。
七、集群搭建
cluster來世今生
在kong v0.11版本去除了cluster這個命令和api的管理,我也是吭哧吭哧花了好長時間找到了如下珍貴的文檔(upgrade to 0.11.x這一節):
kong 0.11 changeLog節選:
Due to the removal of Serf, Kong is now entirely stateless. As such, the /cluster endpoint has for now disappeared. This endpoint, in previous versions of Kong, retrieved the state of the Serf agent running on other nodes to ensure they were part of the same cluster. Starting from 0.11, all Kong nodes connected to the same datastore are guaranteed to be part of the same cluster without requiring additional channels of communication. The Admin API /status endpoint does not return a count of the database entities anymore. Instead, it now returns a database.reachable boolean value, which reflects the state of the connection between Kong and the underlying database. Please note that this flag does not reflect the health of the database itself.
意思是說在kong 0.11之前的版本有cluster命令和/cluster接口來管理kong集群(難怪在0.13中死活提示cluster命令不存在),默認配置文件中有相關cluster參數(網上能搜到很多此類的文檔,不過都是0.10之前的版本),也會有個數據庫表來存儲kong 集群節點相關信息。
但是0.11版本后去除了這個cluster管理這個功能,kong變成完全無狀態的,只要是連接到同一個kong數據庫的節點都認為是同一個kong集群而不需要額外的通信機制。因此也不需要在kong.conf中配置cluster相關參數了。
集群實踐
在0.10之前的版本集群配置也很簡單,參考官方文檔通過cluster命令即可,配置文件默認也是生成好的。相關可參考:http://blog.100dos.com/2016/08/01/kong-cluster-introduction/
接下來我來嘗試一下部署將兩個kong節點連接到同一個pg數據庫,並驗證是否在一個集群。
node1 : 172.18.18.1
node2:172.18.18.2
首先部署好兩個kong節點,並且配置文件連接到同一postgres數據庫。便於測試, 將兩個kong節點的配置文件下面兩個參數為:
proxy_listen = 0.0.0.0:8000 admin_listen = 0.0.0.0:8001
連接相同的數據庫,在kong.conf中設置posgres的連接參數:
pg_host = 172.1.1.2 # The PostgreSQL host to connect to. pg_port = 5432 # The port to connect to. pg_user = kong # The username to authenticate if required. pg_password = kong # The password to authenticate if required. pg_database = kong # The database name to connect to.
注意:數據庫部署的配置文件需要設置允許外部連接,詳見centeos部署pg和kong
配置好后重啟兩個節點的kong服務。
curl 172.18.18.1:8001/status 和curl 172.18.18.2:8001/status 的數據庫連接均為true
{ "database": { "reachable": true }, "server": { "connections_writing": 1, "total_requests": 5, "connections_handled": 4, "connections_accepted": 4, "connections_reading": 0, "connections_active": 1, "connections_waiting": 0 } }
通過node1來注冊一個服務:
curl -i -X POST \ --url http://172.18.18.1:8001/services/ \ --data 'name=service-stock' \ --data 'url=http://hq.sinajs.cn'
顯示注冊成功:
HTTP/1.1 201 Created Date: Sun, 10 Jun 2018 09:43:49 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "host": "hq.sinajs.cn", "created_at": 1528595029, "connect_timeout": 60000, "id": "0032fa88-c457-4d35-b1e7-b5b6f872e2fe", "protocol": "http", "name": "service-stock", "read_timeout": 60000, "port": 80, "path": null, "updated_at": 1528595029, "retries": 5, "write_timeout": 60000 }
通過node2來查詢這個Service:
$ curl -i -X GET --url http://172.18.18.2:8001/services/service-stock HTTP/1.1 200 OK Date: Sun, 10 Jun 2018 09:47:05 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 {"host":"hq.sinajs.cn","created_at":1528595029,"connect_timeout":60000,"id":"0032fa88-c457-4d35-b1e7-b5b6f872e2fe","protocol":"http","name":"service-stock","read_timeout":60000,"port":80,"path":null,"updated_at":1528595029,"retries":5,"write_timeout":60000}
因為二者是共享同一數據庫的,所以這顯然沒有問題。
現在則可以橫向擴展任意多個node節點,只要它們連接的是同一個數據庫(或集群)即可,如果kong對外希望是一個入口,則可以將這些kong節點作為反向代理的上游,通過nginx轉發即可。
參考文檔: