kong 集羣將使得系統經過增長更多機器,從而實現水平擴展,承接更多的請求流量。它們將共享一樣的配置且使用同一個數據庫。kong 集羣中的的全部節點都鏈接同一個數據庫。html
你須要在 kong 集羣的上一層架設一個負載均衡的代理服務器,以便請求可以平均分散轉發到 kong 的各個節點上。node
擁有Kong羣集並不意味着客戶端流量將在開箱即用的Kong節點中實現負載平衡,仍然須要在Kong節點前面使用負載平衡器來分配流量。相反,Kong羣集意味着這些節點將共享相同的配置。nginx
出於性能緣由,Kong在代理請求時避免數據庫鏈接,並將數據庫的內容緩存到內存中。cached實體包括services,routes,consumers,plugins,credentials等...因爲這些值在內存中,所以經過其中一個節點的Admin API進行的任何更改都須要傳播到其餘節點。git
本文檔將介紹,如何使得這些本地緩存失效,而且如何配置 kong 集羣節點,以便支持更多的使用場景,從而在性能和數據強一致性兩方面作出平衡的選擇。github
只有一個 kong 節點鏈接數據庫(Cassandra或PostgreSQL)的單節點 kong 集羣,任何經過 Admin api 的更改,都會當即全局生效。好比:數據庫
假設只有一個kong單節點A ,若是咱們刪除一個已經註冊的Service:json
$ curl -X DELETE http://127.0.0.1:8001/services/test-service
隨後任何關於 kong節點A 請求都將會返回 「404 Not Found」,由於該節點已經在本地刪除中清除了緩存。api
$ curl -i http://127.0.0.1:8000/test-service
在一個多節點 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)將使緩存的數據庫命中無效。
能夠在Kong配置文件中配置3個屬性,其中最重要的一個屬性是db_update_frequency,它決定了Kong節點在性能與一致性之間的權衡。
kong 已經提供了默認的配置,爲了讓你權衡集羣性能和數據一致性兩個方面,避免意外的結果。你能夠按照下面的配置步驟,改變配置的值,從而確保性能和數據一致性可以被接受。
該配置決定 kong 節點從數據庫拉取緩存無效事件,同步任務執行的頻率。一個更小的值意味着同步任務將會更頻繁的執行,kong 節點的緩存數據將保持和數據庫更強的一致性。一個更大的值,意味着你的 kong 節點花更少的時間去處理同步任務,從而更加將更多資源集中去處理請求。
Note:變動將會在db_update_frequency 秒後在整個集羣節點中生效。
若是你的數據庫也是集羣的而且最終一致性的(好比:Cassandra),你必須配置該值。它將確保db_update_propagation秒後,數據庫節點間的變化在整個數據庫集羣中全部節點生效。當配置了該值,kong 節點從同步任務中接收無效事件,清除本地緩存將會延遲 db_update_propagation 秒。
若是一個 kong 節點鏈接到最終一致性數據庫上,且沒有延遲事件須要處理,它可能會清除緩存,而後把沒有更新的值再次緩存起來。(由於這個改變尚未傳播到數據庫集羣的每個節點,註釋:數據庫一致性尚未在數據庫集羣中達到一致,此時kong緩存到期了,可是沒有更新到變化事件,此時會把沒有更新的值再次緩存起來,致使kong也出現不一致,即使kong執行了同步任務。)。
你應該配置該值,經過評估數據庫集羣發生變動後,最終達到一致性所須要的時間。(確保數據庫一致以後,纔去執行 kong 同步任務處理變動事件,從而達到kong 數據一致性)
Note:當配置了該配置項,數據變動傳播到 kong 集羣的最大時間是 db_update_frequency + db_update_propagation 秒。
該配置項的時間(單位秒)是 kong 緩存數據庫實體的時間(包括緩存命中或者穿透),該存活時間是一種保護措施,以防 kong 節點漏掉處理緩存無效事件,避免舊數據長時間沒有被清理。當緩存生存時間到了,緩存值將會被清理掉,下一次將會從數據庫讀取數據並再次緩存起來。
若是使用 Cassandra 做爲 kong 的數據庫,你必須配置 db_update_propagation 爲一個非零值。因爲 Cassandra 自己是最終一致性數據庫,這將確保 kong 節點不會過早地使本地緩存失效,僅僅當再次獲取到一個不是最新值的時候。若是你使用了 Cassandra 但你沒有配置該值時,kong 將會輸出一條警告日誌。
此外,你能夠配置 cassandra_consistency 的值爲:好比 QUORUM 或者 LOCAL_QUORUM,確保被kong 緩存的值是數據庫中最新的。
因爲某些緣由,你但願經過 kong 查看緩存的值,或者手動清理緩存(當緩存被命中或者丟失),你能夠經過使用 Admin api /cache 接口進行管理。
Endpoint
GET /cache/{cache_key}
Response
返回值 當 key 被有效緩存: HTTP 200 OK ... { ... } 不然: HTTP 404 Not Found
注意:檢索由Kong緩存的每一個實體的cache_key目前是一個未公開的過程。 Admin API的將來版本將使此過程更加簡單。
Endpoint
DELETE /cache/{cache_key}
Response
HTTP 204 No Content ...
Endpoint
DELETE /cache
Response
HTTP 204 No Content
注意:請謹慎在生產運行節點上使用此接口。若是節點接收到大量流量,同時清除其緩存將觸發對數據庫的許多請求,並可能致使DB請求堆積現象。
在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轉發便可。