负载均衡(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. TreeSet排序相关总结

            java的集合这一块在工作中用得还比较多,有些东西老是忘,因此在此记录下来. TreeSet原理 1.特点 TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺 ...

  2. 【Java框架型项目从入门到装逼】第十一节 用户新增之把数据传递到后台

    让我们继续来做"主线任务",这一节,我们来做具体的用户新增功能.首先,为了简单起见,我把主页面改了一些,改的是列表那一块.删去了一些字段,和数据库表对应一致: 现在,我们要实现一个 ...

  3. mfc Edit控件属性

    设置Edit控件属性 窗口创建顺序 初始化Edit控件数据 一.设置Edit控件属性 .Align Text :Right 二.窗口创建顺序 CMywindowdlg: 窗口构造函数 OnCreate ...

  4. laraver框架学习------工厂模型填充测试数据

    在laravel中填充数据有几种方式.一种是Seeder,另一种是工厂模式进行的填充. 工厂模式可以实现大批量的填充数据,数据的量可以自定义.这也为后续的软件测试提供方便. 在laravel框架有da ...

  5. 苹果电脑获取Android Studio的发布版SHA1和开发版SHA1

    最近开始转战安卓,准备把我在苹果上的应用也在安卓上来一波,其中就遇到一个问题就是最牛天气(iOS和微信小程序都已经有了,就差安卓的了)引用的百度的定位功能,需要填写发布版SHA1和开发版SHA1,作为 ...

  6. Ing_制作在线QQ

    制作在线QQ的具体步骤 1.首先登录到http://is.qq.com/webpresence/code.shtml 网站2.选择风格3.填写相关数据4.生成网页代码5.复制代码到“写字板”,另存文件 ...

  7. Metasploit 暴力破解演示

    本文简要演示使用Metasploit 中的mysql_login.postgresql_login.tomcat_mgr_login模块暴力破解Metasploitable 2 上部署的服务. Pre ...

  8. java 软件开发面试宝典

    一. Java 基础部分........................................................................................ ...

  9. JAVA笔试准备

    建立时间:2019.4.19 修改时间: 腾讯:选择题(30个,一小时内),简答(2道)和编程题(2道) 涉及内容:(也有可能全是算法)C++,JAVA,数据结构,网络,Linux,计算题 1. 磁盘 ...

  10. error: Build input file cannot be found: '*******/node_modules/react-native/Libraries/WebSocket/libfishhook.a' 问题解决记录

    解决了刚才的'config.h' file not found问题,本以为就可以顺畅的跑起来,谁知道又被恶心到了,Build input file cannot be found!!! 问题: err ...