簡介
Kong為后臺服務(wù)提供了多種負載均衡策略,一種是簡單的基于 DNS 的方法赡突,還有一種更加動態(tài)的 ring-balancer与帆,無需 DNS 服務(wù)器就可以實現(xiàn)服務(wù)注冊
基于 DNS 的負載均衡
當使用基于 DNS 的負載均衡時,后端服務(wù)的注冊是在Kong之外完成的孩锡,Kong只接收來自 DNS 服務(wù)器的更新署辉,所有 host
屬性里包含 hostname (而不是ip地址)的服務(wù)都會自動使用基于 DNS 的負載均衡策略,前提是 hostname 不能解析為 upstream 名或者 hostname 在 DNS hosts 文件里
DNS記錄中的 ttl
決定了信息的更新頻率,如果 ttl
設(shè)置為0剑辫,每個請求都會發(fā)起DNS查詢,顯然這會造成性能問題渠欺,但是DNS的更新妹蔽、改變延遲會相對非常低
A records
A record 包含一個或多個IP地址,因此當主機名解析為 A record 時,每個后端服務(wù)必須有自己的 IP 地址胳岂,因為沒有附加權(quán)重
信息编整,所以此時負載平衡策略就是簡單的輪詢策略
SRV records
SRV record 中包含了所有 IP 地址的權(quán)重和端口信息,單個后端服務(wù)通過IP地址和端口組合標識乳丰,所以一個 IP 地址可以在不同端口上啟動同一個服務(wù)的不同實例掌测,并且由于有權(quán)重信息,用戶可以將負載均衡配置成加權(quán)輪詢策略
同樣产园,端口信息都會被 DNS 服務(wù)器的端口所覆蓋汞斧,如果服務(wù)的屬性為 attributes host=myhost.com
和 port=123
,myhost.com
解析為 SRV 記錄為 127.0.0.1:456
淆两,請求會代理到 http://127.0.0.1:456/somepath
断箫,123
端口會被覆蓋成 456
端口
DNS 優(yōu)先級
DNS解析器按順序解析以下記錄類型:
- 上一個解析成功的類型
- SRV 記錄 - 添加服務(wù)記錄服務(wù)器服務(wù)記錄時會添加此項,SRV記錄了哪臺計算機提供了哪個服務(wù)秋冰,格式為:服務(wù)的名字.協(xié)議的類型(例如:_example-server._tcp)
- A記錄 - 將域名指向一個IPv4地址(例如:100.100.100.100)仲义,需要增加A記錄
- CNAME 記錄 - 如果將域名指向一個域名,實現(xiàn)與被指向域名相同的訪問效果剑勾,需要增加CNAME記錄
這個順序可以通過dns_order
屬性配置
DNS 注意項
- 每當DNS記錄刷新時埃撵,Kong會生成一份列表正確處理權(quán)重信息,計算方式是將權(quán)重保持為彼此的倍數(shù)虽另,比如17和31的權(quán)重配比會生成527條條目暂刘,16和32(對應(yīng)為1和2)的權(quán)重配比會生成3條條目,即使
ttl
屬性為0捂刺,Kong也會更新這份列表 - 不是所有的 nameserver 都會返回所有條目(因為UDP包大小的限制谣拣,比如Consul只會最多返回3條),這樣Kong只會使用 nameserver 提供給它的極少量的 upstream service族展,這種情況下森缠,upstream service 可能會加載不一致,因為Kong沒有有效感知到這些服務(wù)存在仪缸,想要避免這種情況可以換一類 nameserver贵涵,或者使用 IP 地址,而不是名稱恰画,或者確保使用足夠多的Kong節(jié)點可以使用所有的 upstream service
- 當 nameserver 返回
3 name error
宾茂,這對于Kong是有效響應(yīng),如果不想收到這個響應(yīng)拴还,先檢查名稱是否正確跨晴,再檢查 nameserver 的配置是否正確 - 從 DNS 記錄中首次挑選 IP 地址不是隨機的,所以當
ttl
設(shè)置為0時片林,nameserver 會隨機記錄條目
ring-balancer
當使用 ring-balancer 時端盆,Kong會處理服務(wù)的加載和解綁树瞭,就不需要DNS更新了,Kong相當于一個服務(wù)注冊中心爱谁,此時可以在節(jié)點上添加或刪除單個Http請求,以快速接入和斷開流量孝偎,用戶可以通過 upstream
和 target
實體配置 ring-balancer:
-
target
:后端服務(wù)所在的 IP 地址或者主機名加上端口號访敌,例如192.168.100.12:80
,每個target都有一個額外的weight
屬性標識它的相對負載衣盾,IP地址支持 IPv4 和 IPv6 兩種格式 -
upstream
:虛擬主機名寺旺,例如weather.v2.service
Upstream
每個 upstream 都有自己的 ring-balancer,每個 upstream 上可以綁定很多 target 條目势决,當請求代理到虛擬主機名后會負載均衡到這些 target 上阻塑,ring-balancer 有預(yù)定數(shù)量的槽,并且基于 target 的權(quán)重果复,這些槽會分配給對應(yīng)的 target
用戶可以調(diào)用 Admin API 請求添加或者刪除 target陈莽,這個操作比較輕量,相對來說更改 upstream 本身操作比較重量級虽抄,因為 ring-balancer 需要重新構(gòu)建
只有當清理歷史 target 記錄時走搁,ring-balancer 會自動構(gòu)建,除此之外就是收到更改請求
每個 target 使用的插槽數(shù)量應(yīng)該至少大于100迈窟,以確保插槽正確分布私植,例如如果預(yù)期最多有8個 target,那么 upstream 至少定義 slots=800
车酣,即使最初僅設(shè)置兩個 target曲稼,這里需要權(quán)衡的是,插槽數(shù)越多湖员,隨機分布越好贫悄,但修改(增加、刪除 target)的成本也變高
更多信息參考 Admin API 的 upstream 章節(jié)
Target
因為 upstream
會保留歷史的變化破衔,所以只能添加 target
清女,不能修改和刪除,如果想要修改 target
晰筛,只要為此 target
增加一個條目嫡丙,并且修改權(quán)重值,系統(tǒng)將會使用最新添加的條目读第,如果想將 target
從 ring-balancer 中刪除曙博,只需要將其權(quán)重設(shè)置為0,有關(guān)添加和操作 target 的詳細信息可以參考 Admin API 的 target 章節(jié)
當非活動條目數(shù)比活動條目數(shù)多10倍時怜瞒,將自動清除 target父泳,清除將涉及重建 ring-balancer般哼,這比新添加一個 target 條目消耗更高
target
可以是主機名而不是 IP 地址,在這種情況下惠窄,Kong會解析主機名蒸眠,并將所有的條目單獨添加到 ring-balancer 中,比如杆融,用戶添加主機名為api.host.com:123
的條目楞卡,權(quán)重是100,api.host.com:123
主機名可以解析成兩個ip地址脾歇,那么這兩個ip地址對應(yīng)的條目都會添加到 target 中蒋腮,并且每個權(quán)重均為100
如果主機名解析為 SRV 記錄,那么Kong會拾取 DNS 記錄對應(yīng)的端口和權(quán)重藕各,并將其覆蓋成123端口池摧,且權(quán)重為100
ring-balancer 會保留 DNS 記錄的 ttl
設(shè)置,當它過期后會重新請求并更新 ring-balancer激况,例外情況:如果一個 DNS 記錄的 ttl=0
作彤,主機名會被作為單獨的 target 配置,當路由到該 target 后乌逐,Kong會重新尋找 nameserver
負載均衡策略
默認情況下宦棺,ring-balancer 使用加權(quán)輪詢策略,同時也支持基于哈希算法路由黔帕,哈希的輸入值可以是 none
代咸,consumer
,ip
成黄,header
或者 cookie
呐芥,當輸入為 none
時,會啟用加權(quán)輪詢策略奋岁,哈希策略將失效
一般一組哈希策略會有兩個屬性值思瘟,主屬性和 fallback 屬性(當主屬性不可用時),不同的哈希策略包括:
-
none
:不使用哈希策略闻伶,使用加權(quán)輪詢策略(默認) -
consumer
:使用消費者Id作為哈希輸入滨攻,如果沒有消費者Id,則降級到使用憑證Id(外部驗證比如Idap) -
ip
:遠程 IP 地址作為哈希輸入蓝翰,使用此選項時光绕,需要確認實際 IP 的配置設(shè)置 -
header
:使用特定的請求頭作為哈希輸入,一般為hash_on_header
或hash_fallback_header
-
cookie
:使用特定路徑下(hash_on_cookie_path
屬性畜份,默認是"/"
)的特定 cookie 名(hash_on_cookie
屬性)作為哈希輸入诞帐,如果請求中不存在 cookie,會在響應(yīng)中設(shè)置爆雹,如果cookie
作為哈希策略主屬性停蕉,那么hash_fallback
設(shè)置將不生效
哈希算法基于散列一致(ketama 原理)愕鼓,當用戶修改 target 時(增加、刪除慧起、使失效或者更改權(quán)重等操作)菇晃,它會確保修改 ring-balancer 本身修改,保證盡量擊中 upstream service蚓挤,更多信息參考 Admin API 的 upstream 章節(jié)
負載均衡注意項
ring-balancer 可用于單節(jié)點谋旦,也適用于集群,使用加權(quán)輪詢算法時兩者沒有太大區(qū)別屈尼,但使用哈希算法時需要確保所有的節(jié)點都使用了完全相同 ring-balancer,為此必須以相同的方式構(gòu)建 ring-balancer
- 在Kong集群中使用哈希算法時拴孤,target 的條目只能添加 IP 地址脾歧,不能使用 nameserver
- 在對輸入使用哈希算法時,確保輸入的值足夠多樣以獲得均勻分布的哈希演熟,哈希值可以通過CRC-32算法計算鞭执,比如用戶的系統(tǒng)有成千上萬的用戶,但是僅定義了少量消費者(比如三個消費者:Web芒粹,IOS和Android)兄纺,那么通過消費者定義來計算哈希值是不夠的,選擇遠程
ip
地址作為哈希值會得到更好的效果化漆;同理估脆,如果所有的客戶端都集中在同一個 NAT 網(wǎng)關(guān)下,使用cookie
會比使用ip
效果更好
藍綠發(fā)布
使用 ring-balancer 可以輕松為服務(wù)編排藍綠部署座云,僅需發(fā)送 PATCH
指令修改 host
就能動態(tài)切換 target 疙赠,設(shè)置藍色
環(huán)境,啟動服務(wù)版本1:
# 創(chuàng)建upstream
curl -X POST http://kong:8001/upstreams --data "name=address.v1.service"
# 在upstream上創(chuàng)建兩個target
curl -X POST http://kong:8001/upstreams/address.v1.service/targets --data "target=192.168.34.15:80" --data "weight=100"
curl -X POST http://kong:8001/upstreams/address.v1.service/targets --data "target=192.168.34.16:80" --data "weight=50"
# 創(chuàng)建一個服務(wù)指向綠色環(huán)境
curl -X POST http://kong:8001/services/ --data "name=address-service" --data "host=address.v1.service" --data "path=/address"
# 最后創(chuàng)建一個路由作為這個服務(wù)的端點
curl -X POST http://kong:8001/services/address-service/routes/ --data "hosts[]=address.mydomain.com"
此時朦拖,主機名為 address.mydomain.com
的請求會代理到定義的 target圃阳,2/3的流量代理到 http://192.168.34.15:80/address
(權(quán)重為100),1/3的流量代理到 http://192.168.34.16:80/address
(權(quán)重為50)
在發(fā)布服務(wù)版本2前璧帝,先設(shè)置綠色
環(huán)境:
# 創(chuàng)建綠色環(huán)境的upstream
curl -X POST http://kong:8001/upstreams --data "name=address.v2.service"
# 在upstream上創(chuàng)建兩個target
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.17:80" --data "weight=100"
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.18:80" --data "weight=100"
用戶可以更新服務(wù)捍岳,激活藍/綠開關(guān):
curl -X PATCH http://kong:8001/services/address-service --data "host=address.v2.service"
現(xiàn)在主機名為 address.mydomain.com
的請求會代理到新的 target,一半的流量代理到 http://192.168.34.17:80/address
(權(quán)重為100)睬隶,一半的流量代理到 http://192.168.34.18:80/address
(權(quán)重為100)
與往常一樣锣夹,通過Kong Admin API修改權(quán)重變化是動態(tài)的,并會立即生效苏潜,不需要重啟也不需要重新加載晕城,也不會丟棄正在進行中的請求
金絲雀發(fā)布
使用 ring-balancer 可以精準調(diào)節(jié) target 的權(quán)重,從而實現(xiàn)平穩(wěn)窖贤、受控的金絲雀發(fā)布砖顷,這是一個非常簡單的調(diào)控2個 target的示例:
# Target1 權(quán)重為1000
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.17:80" --data "weight=1000"
# Target2 權(quán)重為0
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.18:80" --data "weight=0"
通過重復(fù)這些請求贰锁,但每次改變權(quán)重,流量將慢慢路由到另一個 target滤蝠,此處將其設(shè)置為10%:
# Target1 權(quán)重為900
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.17:80" --data "weight=900"
# Target2 權(quán)重為100
curl -X POST http://kong:8001/upstreams/address.v2.service/targets --data "target=192.168.34.18:80" --data "weight=100"
通過Kong Admin API修改權(quán)重變化是動態(tài)的豌熄,并會立即生效,不需要重啟也不需要重新加載物咳,也不會丟棄正在進行中的請求