负载均衡(Load balancing)是一种计算机网络技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最佳化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。

使用带有负载均衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载均衡服务通常是由专用软体和硬件来完成。

对于互联网服务,负载均衡器通常是一个软体程序,这个程序侦听一个外部端口,互联网用户可以通过这个端口来访问服务,而作为负载均衡器的软体会将用户的请求转发给后台内网服务器,内网服务器将请求的响应返回给负载均衡器,负载均衡器再将响应发送到用户,这样就向互联网用户隐藏了内网结构,阻止了用户直接访问后台(内网)服务器,使得服务器更加安全,可以阻止对核心网络栈和运行在其它端口服务的攻击。

当所有后台服务器出现故障时,有些负载均衡器会提供一些特殊的功能来处理这种情况。例如转发请求到一个备用的负载均衡器、显示一条关于服务中断的消息等。负载均衡器使得 IT 团队可以显著提高容错能力。它可以自动提供大量的容量以处理任何应用程序流量的增加或减少。

  对于核心 api,需要保证搞可靠性,那么就要对于该 api 有多个 backend service,即实际后端对该 api 有多个服务的节点;那么最好在 api-gateway 即 kong 这一层实现负载均衡。
  Kong为多个后端服务提供了多种负载平衡请求方式:一种基于DNS的简单方法,以及一种更加动态的环平衡器,该方法还允许在不需要DNS服务器的情况下进行服务注册。

基于DNS的负载均衡

  当使用基于DNS的负载均衡时,后端服务的注册是在Kong以外完成的,而Kong仅接收来自DNS服务器的更新。

如果名称解析为多个IP地址,并且主机名未解析为上游名称或名称,则每个使用包含hostname(而不是IP地址)的host定义的service都将自动使用基于DNS的负载平衡你的DNS hosts文件。

DNS记录ttl设置(生存时间)决定信息刷新的频率。当使用0的ttl时,每个请求都将使用自己的DNS查询来解析。很明显,这会导致性能下降,但更新/更改的延迟将非常低。

A记录

  A记录包含一个或多个IP地址。因此,当主机名解析为A记录时,每个后端服务都必须具有自己的IP地址。

由于没有weight信息,因此所有条目在负载平衡器中将被视为具有相同的权重,并且平衡器(balancer)将进行简单的循环。

SRV记录

  SRV记录包含所有IP地址的权重(weight)和端口(port)信息。后端服务可以通过IP地址和端口号的唯一组合来识别。因此,单个IP地址可以在不同的端口上托管同一服务的多个实例。

由于weight信息可用,每个条目将在负载均衡器中获得自己的权重,并执行加权循环。

同样,任何给定的端口信息都将被来自DNS服务器的端口信息覆盖。如果服务具有host = myhost.com和port = 123的属性,并且myhost.com解析为具有127.0.0.1:456的SRV记录,则该请求将被代理到http://127.0.0.1:456/somepath,因为123端口将被456覆盖。

DNS优先级

DNS解析器将按顺序解析以下记录类型:

  • 上次解析的最后一次成功类型(LAST)
  • SRV记录
  • A记录
  • CNAME记录

该顺序可通过dns_order配置属性进行配置。
解析不同记录类型的顺序。 LAST类型表示上次成功查找的类型(用于指定的名称)。格式是一个(不区分大小写)逗号分隔的列表。

默认值:LAST,SRV,A,CNAME

DNS警告(DNS caveats)

  • 无论何时刷新DNS记录,都会生成一个列表以正确处理权重。尽量保持权重为对方的倍数以保持算法的高效性,例如,17和31的2个权重将导致具有527个项目的结构,而权重16和32(或其最小的相对对应项1和2)将导致在只有3个条目的结构中,尤其是具有非常小(甚至0)ttl值的结构。
  • 在这些情况下,某些域名服务器不会返回所有条目(由于UDP数据包的大小)(例如Consul最多返回3个),给定的Kong节点将只使用由名称服务器提供的少数上游服务实例。在这种情况下,由于名称服务器提供的信息有限,Kong节点实际上不了解某些实例,因此上游实例池可能会不一致地加载。为了缓解这种情况,可以使用不同的名称服务器,使用IP地址而不是名称,或者确保使用足够的Kong节点来继续使用所有上游服务。
  • 当名称服务器返回3 name error时,那么对于Kong来说这是一个有效的响应。如果这是意外,请首先验证是否正在查询正确的name,然后检查您的nameserver配置。
  • 从DNS记录(A或SRV)中初始选择IP地址不是随机的。因此,当使用ttl为0的记录时,nameserver应该随机记录条目。

环平衡器(ring-balancer)

  当使用环平衡器时,添加和删除后端服务将由Kong处理,并且不需要DNS更新。kong将担任服务登记。节点可以通过一个HTTP请求added/deleted,并立即start/stop接收流量。

配置环平衡器是通过上游和目标实体完成的

  target:具有后端服务驻留端口号的IP地址或主机名,例如。 “192.168.100.12:80”。每个target都会得到一个额外的权重来指示它获得的相对负载。 IP地址可以是IPv4和IPv6两种格式。

  upstream:可以在路由主机字段中使用的'virtual hostname',例如,上游命名的weather.v2.service将从具有host = weather.v2.service的服务获得所有请求

上游(upstream)

  每个upstream都有自己的环形平衡器。每个upstream可以有许多target条目附加到它,代理到'virtual hostname'的请求将在target上进行负载平衡。环形平衡器具有预定义(pre-defined)数量的槽(number of slots),并且基于目标权重,槽(slots)被分配给上游的目标。

  添加和删​​除目标可以通过Admin API上的简单HTTP请求完成。这个操作相对便宜。改变上游本身更昂贵,因为例如当槽的数量改变时平衡器将需要重建。

  自动重建平衡器的唯一情况是清理目标历史记录时;除此之外,它只会在改变时重建。

在平衡器内部有(从1到slots)的位置,它们随机分布( randomly distributed)在环上。在运行时需要随机性来调用环平衡器。轮子上的简单循环(位置)将为目标提供良好的分布式加权循环,同时在插入/删除目标时也具有廉价的操作。

每个目标使用的插槽数量(至少)应该在100个左右,以确保插槽正确分布。例如。对于预期最多8个目标,即使初始设置仅包含2个目标,上游应至少定义为slot = 800。

这里的折衷是,插槽数量越多,随机分布越好,但更改更为昂贵(添加/删除目标)

有关添加和操作上游的详细信息,请参阅Admin API

目标(target)

  由于上游保留了更改历史记录,目标只能添加,不能修改或删除。要更改目标,只需为目标添加一个新条目,然后更改重量值。最后一个条目是将要使用的条目。因为这样的设置权重= 0将禁用目标,有效地从平衡器中删除它。有关添加和操作目标的详细信息,请参阅Admin API参考的目标部分。

  当活动条目比活动条目多10倍时,目标将自动清除。清洁将涉及重建平衡器,因此比添加目标条目更昂贵。

目标也可以具有主机名而不是IP地址,在这种情况下,名称将被解析,所有找到的条目将被单独添加到环形平衡器中,例如,添加api.host.com:123且权重= 100。名称'api.host.com'解析为具有2个IP地址的A记录。然后这两个IP地址将被添加为目标,每个获得weight = 100和端口123.注意:权重用于单个条目,而不是整个!

它是否会解析为SRV记录,然后DNS记录中的端口和权重字段将被拾取,并且会否定给定的端口123和权重= 100。

平衡器将遵守DNS记录的ttl设置和重新查询,并在平衡器到期时更新。

例外情况:当DNS记录的ttl = 0时,主机名将被添加为具有指定权重的单个目标。在对该目标的每个代理请求时,它将再次查询名称服务器。

平衡算法

  默认情况下,环平衡器将使用加权循环方案。另一种方法是使用基于散列的算法。散列的输入可以是none,consumer,ip或header。如果设置为none,则将使用加权循环方案,并且散列将被禁用。

有两种选择,一种primary 和 一种回退(fallback),以防primary失败(例如,如果primary设置为consumer,但没有consumer通过验证)

不同的散列选项:

  • none:不要使用散列,而是使用weighted-round-robin(默认)。
  • consumer:使用消费者ID作为散列输入。如果没有消费者ID可用(如果使用外部身份验证,如ldap),此选项将回退到凭证ID。
  • ip:远程(始发)IP地址将用作输入。在使用此设置时,查看确定真实IP的配置设置。
  • header:使用指定的标题(在hash_on_header或hash_fallback_header字段中)作为散列的输入。

哈希算法基于'一致哈希'(或'ketama原理'),它确保当平衡器通过改变目标(添加,移除,失败或改变权重)而被修改时,只有最小数量的哈希损失发生。这将最大化上游缓存命中。

有关确切设置的更多信息,请参阅Admin API参考的上游upstream部分。

平衡警告(Balancing caveats)

  环平衡器设计为既可以在单个节点上工作,也可以在群集中工作。对于加权循环算法没有太大的区别,但是当使用基于散列的算法时,重要的是所有节点构建完全相同的环平衡器以确保它们都工作一致。要做到这一点,平衡器必须以确定性的方式构建。

  不要在平衡器中使用主机名称,因为平衡器可能会/会慢慢发生分歧,因为DNS ttl只有第二精度,更新取决于实际请求名称的时间。最重要的是一些域名服务器没有返回所有条目的问题,这加剧了这个问题。因此,在Kong群集中使用哈希方法时,只能通过IP地址添加目标实体,而不能通过名称添加target实体。

  当选择你的散列输入时,确保输入具有足够的方差以得到散布良好的散列。哈希将使用CRC-32摘要进行计算。例如,如果您的系统有成千上万的用户,但只有少数用户(每个平台定义了3个用户:Web,iOS和Android),那么挑选consumer散列输入是不够的,通过设置使用远程IP地址对于ip的哈希将提供更多的输入差异,从而更好地分配哈希输出

蓝绿部署(Blue-Green Deployments)

  使用环形平衡器,可以轻松地为一项服务策划一个蓝绿色部署。切换目标基础架构只需要服务上的PATCH请求,即可更改其主机值。

设置“blue”环境,运行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"

在部署version 2 of the address service之前,请设置“green”环境:

# 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"

要激活blue/green开关,现在只需要更新服务:

# Switch the Service from Blue to Green upstream, v1 -> v2
$ curl -X PATCH http://kong:8001/services/address-service \
--data "host=address.v2.service"

主机头设置为address.mydomain.com的传入请求现在由Kong代理到新目标; 1/2的请求将转到http://192.168.34.17:80/address(权重= 100),另一半将转到http://192.168.34.18:80/address(权重= 100 )。

与往常一样,通过Kong Admin API进行的更改是动态的,并且会立即生效。不需要重新加载或重新启动,并且没有进行中的请求将被丢弃。

金丝雀版本(Canary Releases)

  使用环形平衡器,可以精确调整目标重量,从而实现平稳.。

使用一个非常简单的2 target示例:

# first target at
$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.17:80"
--data "weight=1000" # second target at
$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.18:80"
--data "weight=0"

通过重复请求,但每次改变权重,流量将缓慢路由到另一个target。例如,将其设置为10%:

# first target at
$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.17:80"
--data "weight=900" # second target at
$ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \
--data "target=192.168.34.18:80"
--data "weight=100"

通过Kong Admin API进行的更改是动态的,并会立即生效。不需要重新加载或重新启动,并且没有进行中的请求将被丢弃。

KONG负载均衡实现

  实际在操作过程中,采用的是 kong 的 Ring-balancer 做负载均衡。

  使用 Kong Community Edition(社区版 v0.13)来搭建一个负载均衡器,由于 Kong 是基于 Openresty 的,而 Openresty 又是 Nginx 的二次封装,所有很多配置项和 Nginx 类似。

来看一个较为典型的 Nginx 负载均衡配置:

upstream hello {
server localhost: weight=;
server localhost: weight=;
} server {
listen ;
location /hello {
proxy_pass http://hello;
}
}

  nginx 监听来自本地 80 端口的请求,如果路径与 /hello 匹配,便将请求原封不动的转发到名称为 hello 的upstream,而该 upstream 我们配置了一个负载均衡器,会路由到本地的 3000 端口和 3001 端口。

接下来便可以针对 Kong 进行负载均衡的配置了。

配置 upstream 和 target

创建一个名称 hello 的 upstream

curl -X POST http://localhost:8001/upstreams --data "name=hello"  

为 hello 添加两个负载均衡节点

curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3000" --data "weight=100" 
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3001" --data "weight=50" 

如上的配置对应了 Nginx 的配置:

upstream hello {
server localhost: weight=;
server localhost: weight=;
}

配置 service 和 route

  使用 Kong v0.13之前版本的用户可能会接触过 api 这个概念,但是在 Kong v0.13.0 中,已经被废除了,取而代之的是 service 和 route 的配置。

配置一个 service

curl -X POST http://localhost:8001/services --data "name=hello" --data "host=hello" 

host 的值便对应了 upstream 的名称,配置成功后会返回生成的 service 的 id,返回结果:8695cc65-16c1-43b1-95a1-5d30d0a50409。

为上面的 service 配置路由信息

curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id=8695cc65-16c1-43b1-95a1-5d30d0a50409"

请求路径包含 /hello 的请求都会被转移到对应的 service 进行处理。

如上的配置便对应了Nginx的配置:

location /hello {
proxy_pass http://hello;
}

测试 Kong 的负载均衡

curl http://localhost:8000/hello/hi 

因为复杂均衡的原因,需要多测试几次,多次 curl 之后结果如下:


reference:

https://getkong.org/docs/0.13.x/loadbalancing/

https://getkong.org/docs/0.13.x/configuration/

apigateway-kong(四)负载均衡理论及实现的更多相关文章

  1. (课堂笔记)第三章:F5 LTM 负载均衡理论

    BIG-IP LTM负载均衡理论 ------F5 BIG-IP LTM负载均衡策略---------- 1.1 LTM VS工作模式F5 BIG-IP LTM的内部对于数据包的处理方式,即是VS的工 ...

  2. Dubbo 源码解析四 —— 负载均衡LoadBalance

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 Dubbo 入门之二 --- 项目结构解析 Dubbo 源码分析系列之三 -- 架构原 ...

  3. springcloud微服务总结四 负载均衡

    一:Ribbon简介 Ribbon是Netflix公司开源的一个负载均衡的项目,是一个客户端负载均衡器,运行在客户端上.它是一个经过了云端测试的IPC库,可以很好地控制HTTP和TCP客户端的一些行为 ...

  4. LVS负载均衡理论以及算法概要

    一. LVS简介 LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.or ...

  5. HBASE数据模型&扩展和负载均衡理论

    示例数据模型 HBase中扩展和负载均衡的基本单元成为region,region本质上是以行健排序的连续存储区间.如果region太大,系统会把它们 自动拆分,相反的,就是把多个region合并,以减 ...

  6. nginx 反向代理实现负载均衡*理论

    Nginx负载均衡集群介绍 负载均衡集群提供了一种廉价,有效,透明的方法,来扩展网络设备和服务器的负载,带宽和吞吐量,同时加强了网络数据处理能力,提高了网络的灵活性和可用性. 搭建负载均衡服务的需求: ...

  7. kong配置upstream实现简单的负载均衡

    目录 通过konga实现 1. 配置upstream 2. 配置Service发布 3. 配置Route,匹配规则 4. 验证结果 通过 Kong Admin API实现 1. 配置upstream ...

  8. 负载均衡之LVS与Nginx对比

    今天总结一下负载均衡中LVS与Nginx的区别,好几篇博文一开始就说LVS是单向的,Nginx是双向的,我个人认为这是不准确的,LVS三种模式中,虽然DR模式以及TUN模式只有请求的报文经过Direc ...

  9. 12.Nginx代理与负载均衡

    1.什么是代理? 代为办理 --> 代理 2.Nginx正向代理.反向代理 正向代理: --> 上网 | 路由器替代 反向代理: --> 正向与反向代理的区别: 区别在于形式上服务的 ...

随机推荐

  1. EZ 2018 05 13 NOIP2018 模拟赛(十三)

    这次的比赛真心水,考时估分240,然后各种悠闲乱逛 然后测完T1数组开小了炸成40,T2,T3都没开long long,T2炸成20,T3爆0 掉回1600+的深渊,但是还有CJJ dalao比我更惨 ...

  2. 隐马尔科夫模型研究 stock 以及 lotto

    说明 本文参考了这里 由于数据是连续的,因此使用了高斯隐马尔科夫模型:gaussianHMM 一.stock代码 import tushare as ts import pandas as pd im ...

  3. python 生成器按指定大小读取文件

    #!/usr/bin/env python import osimport sys def read_file(fpath): Block_Size = 1024 with open(fpath,&q ...

  4. grunt-inline:一个资源内嵌插件

    一.插件简介 将引用的外部资源,如js.css.img等,内嵌到引用它们的文件里去. 二.使用场景 在项目中,出于某些原因,有的时候我们需要将一些资源,比如js脚本内嵌到页面中去.比如我们的html页 ...

  5. 贪心算法HURUST题目

    题目描述: Yogurt factory The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. ...

  6. gym101522 [小熊骑士限定]La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017

    西瓜队(划掉),Kuma Rider久违的第一场训练,四小时瞎打.jpg A.水题,排序 #include<cstdio> #include<iostream> #includ ...

  7. 机器学习中几种优化算法的比较(SGD、Momentum、RMSProp、Adam)

    有关各种优化算法的详细算法流程和公式可以参考[这篇blog],讲解比较清晰,这里说一下自己对他们之间关系的理解. BGD 与 SGD 首先,最简单的 BGD 以整个训练集的梯度和作为更新方向,缺点是速 ...

  8. 【GAN与NLP】GAN的原理 —— 与VAE对比及JS散度出发

    0. introduction GAN模型最早由Ian Goodfellow et al于2014年提出,之后主要用于signal processing和natural document proces ...

  9. ace how to guide

    Configuring the editor there are several ways to pass configuration to Ace 有几种方法可以将配置传递给ace // pass ...

  10. 软件工程课程设计——第一个Spring

    开发会议框架表格: 1.我们团队Reborn针对需求功能进行热烈的讨论会议,从功能的方面分析开发,结合在一起组合为App软件,再另外思考附加的功能性娱乐项目. 2.开发过程中,以表格的形式反思开发过程 ...