Kong(V1.0.2)loadbalancing
介绍
Kong为多个后端服务提供了多种负载平衡请求的方法:一种简单的基于DNS-based的方法,以及一种更动态的环形负载均衡器ring-balancer,它还允许在不需要DNS服务器的情况下使用service registry。
DNS-based loadbalance
当使用基于DNS-based的负载均衡时,后端服务的注册是在Kong之外完成的,Kong只从DNS服务器接收更新。
如果主机名解析为多个IP地址,则使用包含主机名(而不是IP地址)的主机定义的每个服务将自动使用基于DNS-based的负载平衡,前提是主机名不解析为upstream
名称或DNS主机文件中的名称。
DNS记录ttl设置(生存时间)决定刷新的频率。当ttl为0时,每个请求每次都将使用自己的DNS查询来解析。很明显,这将带来性能损失,但是更新/更改的延迟非常低。
A记录
一条记录包含一个或多个IP地址。因此,当hostname 解析为a记录时,每个后端服务必须有自己的IP地址。
因为没有权重信息,所以在负载均衡器中所有条目的权重都是相等的,均衡器将执行直接的循环。
SRV记录
SRV记录包含其所有IP地址的权重和端口信息。后端服务可以通过IP地址和端口号的唯一组合来标识。因此,一个IP地址可以在不同的端口上承载相同服务的多个实例。
因为权重信息是可用的,所以每个条目将在负载均衡器中获得自己的权重,并执行加权循环。
类似地,来自DNS服务器的端口信息将覆盖任何给定的端口信息。如果一个服务具有host=myhost.com和port=123的属性,并且myhost.com解析为一个SRV记录127.0.0.1:456,那么请求将被代理到http://127.0.0.1:456/somepath,因为端口123将被456覆盖。
DNS优先级
DNS解析器将开始解析以下记录类型,顺序如下:
- 前面解析的最后一个成功类型
- SRV记录
- 一个记录
- CNAME记录
此顺序可通过dns_order
configuration property进行配置。
DNS警告
- 每当刷新DNS记录时,都会生成一个列表来正确处理权重。尽量保持权重作为彼此保持算法性能的倍数,例如,两个权重17和31将转化为527的entries ,而权重16和32(或最小等价1和2)会导致结构仅仅3entries ,尤其是在一个非常小的(甚至0)ttl值。
- 某些命名服务器不返回所有entries (由于UDP包的大小),在这种情况下(例如,Consul 返回最多3entries ),给定的Kong节点将只使用由nameserver提供的少数上游服务实例。在此场景中,上游实例池的加载可能不一致,因为由于nameserver提供的信息有限,Kong节点实际上并不知道某些实例。为了减少这种情况,可以使用不同的名称服务器,使用IP地址而不是名称,或者确保使用足够的Kong节点来仍然使用所有上游服务。
- 当nameserver返回3个名称错误时,这是对Kong的有效响应。如果这是意外的,首先验证查询的名称是否正确,然后检查nameserver配置。
- 从DNS记录(A记录或SRV)中初始选择IP地址不是随机的。因此,当使用ttl为0的记录时,nameserver将随机化记录entries。
Ring-balancer
当使用环形负载均衡器时,后端服务的添加和删除将由Kong处理,不需要DNS更新。Kong将担任服务注册。节点可以通过单个HTTP请求添加/删除,并立即启动/停止接收流量。
通过upstream
和target
entities配置环形负载均衡器。
target:带有后端服务所在端口号的IP地址或主机名,例如。“192.168.100.12:80”。每个目标获得一个额外的权重,以指示它获得的相对负载。IP地址可以是IPv4和IPv6格式。
upstream:可以在Route hiost字段中使用的“虚拟主机名”,例如,upstream名为weather.v2的上游服务将从获得所有带参数host=weather.v2.service的请求。
upstream
每个上游都有自己的环形负载均衡器。每个upstream可以有许多target entries,代理到“虚拟主机名”的请求将在目标上进行负载平衡。一个环形负载均衡器有预先定义的槽数,并且根据目标权重,槽被分配给upstream的目标。
可以通过管理API上的简单HTTP请求来添加和删除目标。这个操作相对简单。更改upstream本身的开销更大,例如,当槽数发生变化时需要重新构建负载均衡器。
只有在清理目标历史记录时,才会自动重新构建均衡器;除此之外,它只会在更改的基础上重新构建。
在负载均衡器中有位置(从1到slots),它们随机分布在环上,为了在运行时廉价地调用环形负载均衡器,需要随机性。一个简单的轮询(位置)就可以在目标上提供一个分布良好的加权轮询,同时在插入/删除目标时具有廉价的操作。
每个目标使用的插槽的数量应该(至少)在100左右,以确保插槽是正确分布的。如。对于最大期望的8个目标,上游应该定义至少插槽=800,即使初始设置只有2个目标。
这里的权衡是插槽的数量越多,随机分布越好,但是更改(添加/删除目标)的成本就越高
关于添加和操作上行流的详细信息可以在Admin API reference的上游部分中获得。
Target
因为upstream
维护更改的历史记录,所以只能添加、不能修改或删除目标。要更改目标,只需为目标添加一个新条目,并更改权重值。最后一个条目将被使用。因此,设置weight=0将禁用目标,从而有效地将其从均衡器中删除。关于添加和操作目标的详细信息可以在Admin API reference的目标部分中找到。
当非活动条目比活动条目多10倍时,将自动清除目标。清理将涉及到重新构建均衡器,因此比仅仅添加目标条目更昂贵。
目标也可以有主机名而不是IP地址。在这种情况下,名称将被解析,找到的所有条目将单独添加到环均衡器中,例如,添加api.host.com:123和weight=100。名称“api.host.com”解析为包含两个IP地址的A记录。然后将两个ip地址都添加为目标,每个ip地址的权值为100,端口为123。注意:权重用于单个条目,而不是整个条目!
如果它解析为SRV记录,那么DNS记录中的端口和权值字段也将被提取,并将否决给定的端口123和权值=100。
均衡器将尊重DNS记录的ttl设置和请求,并在其到期时更新均衡器。
例外:当DNS记录ttl=0时,主机名将作为单个目标添加,并具有指定的权重。每当代理请求这个目标时,它将再次查询名称服务器。
Balancing算法
默认情况下,环型均衡器将使用加权循环方案。另一种选择是使用基于哈希的算法。哈希的输入可以是none、consumer、ip、header或cookie。当设置为none时,将使用加权循环方案,并禁用哈希。
有两个选项,主服务器失败时的主服务器和回退服务器(例如,如果主服务器被设置为使用者,但是没有经过身份验证的使用者)
不同的哈希选项:
- none:不要使用散列,而是使用加权循环(默认)。
- consumer:使用consumer id作为散列输入。如果没有可用的consumer id(对于ldap之类的外部身份验证),则此选项将回退到凭据id上。
- ip:将使用远程(原始)ip地址作为输入。在使用此选项时,请检查确定实际IPdetermining the real IP的配置设置。
- header:使用指定的header(在hash_on_header或hash_fallback_header字段中)作为散列的输入。
- cookie:使用指定的cookie名称(在hash_on_cookie字段中)和指定的路径(在hash_on_cookie_path字段中,默认为“/”)作为哈希的输入。如果cookie不在请求中,它将由响应设置。因此,如果cookie是主要的散列机制,则hash_fallback设置无效。
哈希算法基于“一致性哈希”(或“ketama原则”),它确保当均衡器通过更改目标(添加、删除、失败或更改权重)进行修改时,只会发生最小数目的哈希损失。这将最大化上游缓存命中。
有关确切设置的更多信息,请参见Admin API reference的上游部分
Balancing caveats
环型均衡器被设计成既可以在单个节点上工作,也可以在集群中工作。对于加权循环算法来说差别不大,但是在使用基于散列的算法时,重要的是所有节点构建完全相同的环平衡器,以确保它们的工作方式完全相同。为此,必须以确定的方式构建均衡器。
- 不要在均衡器中使用主机名,因为均衡器可能/将缓慢地偏离,因为DNS ttl只有第二次精度,并且更新取决于实际请求名称的时间。最重要的是一些nameserver不返回所有条目的问题,这加剧了这个问题。因此,在Kong集群中使用散列方法时,只根据目标实体的IP地址添加它们,而不按名称添加。
- 当选择哈希输入时,确保输入有足够的方差来得到一个分布良好的哈希。散列将使用CRC-32摘要计算。因此,例如,如果您的系统有数千个用户,但每个平台只定义了几个consumer(例如。3 consumers:Web, iOS和Android)然后选择consumer哈希输入是不够的,使用远程IP地址通过设置哈希为IP将提供更多的输入方差,因此在哈希输出更好的分布。然而,如果许多客户端位于相同的NAT网关之后(例如在呼叫中心),cookie将提供比ip更好的分布。
Blue-Green Deployments
Using the ring-balancer a blue-green deployment can be easily orchestrated for a Service.切换目标基础设施只需要对服务发出补丁请求,以更改其主机值。
Set up the “Blue” environment, running version 1 of the address service:
# create an upstream
curl -X POST http://kong:8001/upstreams \
--data "name=address.v1.service"
# add two targets to the upstream
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"
# create a Service targeting the Blue upstream
curl -X POST http://kong:8001/services/ \
--data "name=address-service" \
--data "host=address.v1.service" \
--data "path=/address"
# finally, add a Route as an entry-point into the Service
curl -X POST http://kong:8001/services/address-service/routes/ \
--data "hosts[]=address.mydomain.com"
将host header设置为address.mydomain.com的请求现在将由Kong代理到两个已定义的目标;2/3的请求将访问http://192.168.34.15:80/address (weight=100), 1/3的请求将访问http://192.168.34.16:80/address (weight=50)。
在部署address服务的版本2之前,设置“绿色”环境:
# create a new Green upstream for address service v2
curl -X POST http://kong:8001/upstreams \
--data "name=address.v2.service"
# add targets to the upstream
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"
To activate the Blue/Green switch, we now only need to update the Service:
# Switch the Service from Blue to Green upstream, v1 -> v2
curl -X PATCH http://kong:8001/services/address-service \
--data "host=address.v2.service"
将host header信息设置为address.mydomain.com的传入请求现在将由Kong代理到新目标;其中1/2的请求将访问http://192.168.34.17:80/address (weight=100),另外1/2的请求将访问http://192.168.34.18:80/address (weight=100)。
与往常一样,通过Kong Admin API进行的更改是动态的,将立即生效。不需要重新加载或重新启动,也不会删除正在处理的请求。
Canary Releases 金丝雀的版本
Using the ring-balancer, target weights 可以颗粒状调整,允许平稳、可控的金丝雀发布canary release.
Using a very simple 2 target example:
# first target at 1000
curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.17:80"
--data "weight=1000"
# second target at 0
curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.18:80"
--data "weight=0"
通过重复请求,但每次更改权重,流量将缓慢地路由到另一个目标。例如,设置为10%:
# first target at 900
curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.17:80"
--data "weight=900"
# second target at 100
curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.18:80"
--data "weight=100"
The changes through the Kong Admin API are dynamic and will take effect immediately. No reload or restart is required, and no in progress requests will be dropped.