标签归档:负载均衡

centos 7 下haproxy的配置文件详解及haproxy优化

HAProxy虽然名字前有HA,但它并不是一款高可用软件,而是一款用于实现负载均衡的软件,可实现四层与七层的负载均衡。

关于haproxy的常用调度算法,可以参考博文:Haproxy支持的调度算法

haproxy的详细配置过程和配置日志记录,可以参考博文:keepalived+Haproxy搭建高可用Web群集

这篇博文不谈如何配置haproxy,主要来聊一下它的配置文件说明以及生产环境中的参数调优。

haproxy的配置文件通常分为三个部分:global、defaults和listen。依次为全局配置、默

认配置、应用组件配置。

global配置:

global
        log 127.0.0.1   local   #配置日志记录,local0为日志设备,默认存放到系统日志
        log 127.0.0.1   local1 notice  #notice为日志级别,通常有24个级别
        #log loghost    local0 info
        maxconn 4096             #最大连接数
        chroot /usr/share/haproxy         #该服务自设置的根目录,一般需将此行注释掉
        uid 99         #用户UID
        gid 99        #用户GID
        daemon        #守护进程模式

defaults配置项配置默认参数,一般会被应用组件继承,如果在应用组件中没有特别的声明,将安装默认配置参数:

defaults
        log     global               #定义日志为global配置中的日志定义
        mode    http                 #模式为http
        option  httplog              #采用http日志格式记录日志
        option  dontlognull
        retries 3         #检查节点服务器失败次数,连续达到三次失败,则认为节点不可用
        redispatch             #当服务器负载很高时,自动结束当前队列处理比较久的连接
        maxconn 2000                      #最大连接数
        contimeout      5000              #连接超时时间
        clitimeout      50000             #客户端超时时间
        srvtimeout      50000             #服务器超时时间

listen配置项一般配置应用模块参数:

listen  appli4-backup 0.0.0.0:10004           #定义一个名为appli4-backup的应用
                option  httpchk /index.html        #检查服务器的index.html文件
                option  persist     #强制将请求发送到已经down掉的服务器,一般禁用此选项。
                balance roundrobin        #负载均衡调度算法使用轮询算法
            server  inst1 192.168.114.56:80 check inter 2000 fall 3     #定义在线节点
         server  inst2 192.168.114.56:81 check inter 2000 fall 3 backup #定义备份节点
#注意:在以上定义备份节点的参数中,
#“check inter 2000”表示haproxy服务器和节点之间的一个心跳频率,
#“fall 3”表示连续三次检测不到心跳频率则认为该节点失效。
#节点配置后带有“ backup”表示该节点只是个备份节点,只有主节点失效该节点才会上。
#去除backup,表示为主节点,和其他主节点共同提供服务。
haproxy的负载均衡参数说明:

现代网络负载平衡和代理简介

最近引起我注意的是,缺乏关于现代网络负载平衡和代理的介绍性教育材料。我心想:这怎么可能?负载平衡是构建可靠分布式系统所需的核心概念之一。当然必须有高质量的信息吗?我搜索并发现这些采摘确实很苗条。关于负载平衡代理服务器的维基百科文章包含一些概念的概述,但不是对主题的流畅处理,特别是因为它涉及现代微服务架构。一个谷歌搜索的负载均衡主要是轮番上涨是对细节的流行语和轻重供应商的网页。

在这篇文章中,我试图通过提供对现代网络负载平衡和代理的温和介绍来纠正缺乏信息。坦率地说,这是一个可能成为整本书主题的大型话题。为了保持这篇文章(有点)博客篇幅,我尝试将一组复杂的主题提炼成一个简单的概述; 根据兴趣和反馈,我将在稍后考虑更详细的关于个别主题的后续帖子。

有一些背景知道我为什么写这个 – 我们走了!

什么是网络负载平衡和代理?

Wikipedia 负载平衡定义为:

在计算中,负载平衡改善了跨多个计算资源(例如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器)的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间,并避免任何单个资源的过载。使用具有负载平衡而不是单个组件的多个组件可以通过冗余提高可靠性和可用性。负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。

以上定义适用于计算的所有方面,而不仅仅是网络。操作系统使用负载平衡来跨物理处理器调度任务,容器协调器(如Kubernetes)使用负载平衡来跨计算群集调度任务,网络负载平衡器使用负载平衡来跨可用后端调度网络任务。本文的其余部分仅涵盖网络负载平衡

图1:网络负载平衡概述

图1显示了网络负载平衡的高级概述。一些客户端正在从一些后端请求资源。负载均衡器位于客户端和后端之间,并且在高级别执行几项关键任务:

  • 服务发现:系统中有哪些后端可用?它们的地址是什么(即负载均衡器应该如何与它们通信)?
  • 健康检查:目前哪些后端健康且可以接受请求?
  • 负载平衡:应该使用什么算法来平衡健康后端的各个请求?

在分布式系统中正确使用负载平衡可带来以下好处:

  • 命名抽象:客户端可以通过预定义的机制解决负载均衡器,而不是每个客户端需要了解每个后端(服务发现),然后可以将名称解析行为委托给负载均衡器。预定义机制包括内置库和众所周知的DNS / IP /端口位置,并将在下面更详细地讨论。
  • 容错:通过运行状况检查和各种算法技术,负载均衡器可以有效地路由坏的或过载的后端。这意味着操作员通常可以在休闲时修复坏后端,而不是紧急情况。
  • 成本和性能优势:分布式系统网络很少是同质的。该系统可能跨越多个网络区域和区域。在区域内,网络通常以相对不足的方式构建。在区域之间,超额认购成为常态。(在此上下文中,/ underubscription指的是通过NIC消耗的带宽量占路由器之间可用带宽的百分比)。智能负载平衡可以尽可能地保持区域内的请求流量,从而提高性能(减少延迟)并降低整体系统成本(区域之间所需的带宽和光纤更少)。

负载均衡器与代理

在谈论网络负载平衡器时,术语负载平衡器代理在业内大致可互换使用。这篇文章也将这些条款视为一般等同。(小心并非所有代理都是负载均衡器,但绝大多数代理都将负载均衡作为主要功能)。

有些人可能会争辩说,当负载均衡作为嵌入式客户端库的一部分完成时,负载均衡器实际上并不是代理。但是,我认为区别会给已经令人困惑的话题带来不必要的复杂性。负载平衡器拓扑的类型将在下面详细讨论,但是这篇文章将嵌入式负载均衡器拓扑视为代理的特殊情况; 应用程序通过嵌入式库进行代理,该库提供与应用程序进程之外的负载均衡器相同的抽象。

L4(连接/会话)负载平衡

在讨论当今整个行业的负载平衡时,解决方案通常分为两类:L4L7这些类别涉及OSI模型的第4层第7层由于我在讨论L7负载平衡时会变得明显的原因,我认为这些是我们使用的术语是不幸的。OSI模型是负载平衡解决方案的复杂性的非常差的近似,其包括传统的第4层协议(例如TCP和UDP),但通常最终包括在各种不同OSI层的位和协议。即,如果L4 TCP负载均衡器也支持TLS终端,它现在是L7负载均衡器吗?

图2:TCP L4终端负载平衡

图2显示了传统的L4 TCP负载均衡器。在这种情况下,客户端与负载均衡器建立TCP连接。负载均衡器终止连接(即直接响应SYN),选择后端,并与后端建立新的TCP连接(即发送新的SYN)。该图的细节并不重要,将在下面专门讨论L4负载平衡的部分中详细讨论。

本节的关键点是L4负载均衡器通常仅在L4 TCP / UDP连接/会话级别运行。因此,负载均衡器大致来回抽取字节,并确保来自同一会话的字节在同一后端结束。L4负载均衡器不知道它正在混洗的字节的任何应用程序细节。字节可以是HTTP,Redis,MongoDB或任何其他应用程序协议。

L7(应用程序)负载平衡

L4负载平衡很简单,仍然可以广泛使用。L4负载平衡有哪些缺点需要投资L7(应用程序)负载平衡?以下面的L4特定案例为例:

  • 两个GRPC / HTTP2客户希望,使他们通过L4负载均衡器连接到跟一个后端。
  • L4负载均衡器为每个传入的TCP连接建立单个传出TCP连接,从而产生两个传入和两个传出连接。
  • 但是,客户端A通过其连接每分钟发送1个请求(RPM),而客户端B通过其连接发送每秒50个请求(RPS)。

在上一个场景中,选择处理客户端A的后端将处理大约3000倍的负载,然后选择后端来处理客户端B这是一个大问题,并且通常首先会破坏负载平衡的目的。另请注意,任何多路复用保持活动协议都会出现此问题多路复用意味着通过单个L4连接发送并发应用程序请求,并且保持活动意味着在没有活动请求时不关闭连接)。由于效率原因,所有现代协议都在发展为多路复用和保持活动(创建连接通常很昂贵,尤其是当使用TLS加密连接时),因此L4负载平衡器阻抗不匹配随着时间的推移变得越来越明显。此问题由L7负载平衡器修复。

图3:HTTP / 2 L7终端负载平衡

图3显示了L7 HTTP / 2负载均衡器。在这种情况下,客户端与负载均衡器建立单个HTTP / 2 TCP连接。然后负载平衡器继续进行两个后端连接。当客户端向负载均衡器发送两个HTTP / 2流时,流1被发送到后端1,而流2被发送到后端2.因此,即使多路复用具有非常不同的请求负载的客户端也将在后端有效地平衡。这就是L7负载平衡对于现代协议如此重要的原因。(L7负载平衡由于其检查应用程序流量的能力而产生了大量额外的好处,但这将在下面更详细地介绍)。

L7负载均衡和OSI模型

正如我在上面关于L4负载平衡的部分所述,使用OSI模型来描述负载平衡功能是有问题的。原因是L7,至少如OSI模型所描述的那样,本身包含多个离散的负载平衡抽象层。例如,对于HTTP流量,请考虑以下子层:

  • 可选的传输层安全性(TLS)。请注意,网络人员争论TLS属于哪个OSI层。为了便于讨论,我们将考虑TLS L7。
  • 物理HTTP协议(HTTP / 1或HTTP / 2)。
  • 逻辑HTTP协议(标头,正文数据和预告片)。
  • 消息传递协议(gRPC,REST等)。

复杂的L7负载平衡器可以提供与上述每个子层相关的特征。另一个L7负载均衡器可能只有一小部分功能将其置于L7类别中。简而言之,从功能比较的角度来看,L7负载均衡器的格局要比L4类别复杂得多。(当然,本节刚刚介绍了HTTP; Redis,Kafka,MongoDB等都是受益于L7负载平衡的L7应用协议的例子)。

负载平衡器功能

在本节中,我将简要总结负载平衡器提供的高级功能。并非所有负载平衡器都提供所有功能。

服务发现

服务发现是负载均衡器确定可用后端集的过程。方法多种多样,一些例子包括:

健康检查

运行状况检查是负载均衡器确定后端是否可用于提供流量的过程。健康检查通常分为两类:

  • 活动:负载均衡器以固定间隔(例如,对/healthcheck端点的HTTP请求)向后端发送ping,并使用它来衡量运行状况。
  • 被动:负载均衡器从主数据流中检测健康状态。例如,如果一行中存在三个连接错误,则L4负载均衡器可能会判定后端是不健康的。如果连续存在三个HTTP 503响应代码,则L7负载均衡器可能会判定后端运行状况不佳。

负载均衡

是的,负载平衡器必须实际平衡负载!给定一组健康的后端,如何选择后端来提供连接或请求?负载平衡算法是一个活跃的研究领域,范围从简单的算法,如随机选择和循环,到考虑可变延迟和后端负载的更复杂的算法。鉴于其性能和简单性,最流行的负载平衡算法之一被称为2个最小请求负载平衡的功能

粘性会议

在某些应用程序中,同一会话的请求到达相同的后端非常重要这可能与缓存,临时复杂构造状态等有关。会话的定义各不相同,可能包括HTTP cookie,客户端连接的属性或某些其他属性。许多L7负载均衡器对粘性会话有一些支持。顺便说一句,我会注意到会话粘性本质上是脆弱的(托管会话的后端可能会死),所以在设计依赖它们的系统时要小心。

TLS终止

TLS的主题及其在边缘服务和保护服务到服务通信中的作用值得自己发表。话虽如此,许多L7负载均衡器进行了大量的TLS处理,包括终止,证书验证和固定,使用SNI的证书服务等。

观测

正如我在会谈中所说的那样:“可观察性,可观察性,可观察性。”网络本质上是不可靠的,负载均衡器通常负责导出统计数据,跟踪和日志,帮助运营商找出问题所在,以便他们能够解决问题。负载平衡器的可观察性输出差异很大。最先进的负载平衡器提供丰富的输出,包括数字统计,分布式跟踪和可自定义的日志记录。我要指出,增强的可观察性不是免费的; 负载均衡器必须做额外的工作来生产它。但是,数据的好处大大超过了相对较小的性能影响。

安全和DoS缓解

尤其是在边缘部署拓扑(见下文),负载平衡器通常实现的各种安全功能,包括速率限制,认证和DoS缓解(例如,IP地址标记和识别,缓送等)。

配置和控制平面

需要配置负载平衡器。在大型部署中,这可能成为一项重大任务。通常,配置负载平衡器的系统称为“控制平面”,并且在其实现中变化很大。有关此主题的更多信息,请参阅我在服务网格数据平面与控制平面上的帖子

还有更多

本节刚刚介绍了负载均衡器提供的功能类型。有关L7负载平衡器的部分,请参见其他讨论。

负载均衡器拓扑的类型

现在我已经介绍了负载均衡器的概况,L4和L7负载均衡器之间的差异以及负载均衡器功能的摘要,我将继续讨论部署负载均衡器的各种分布式系统拓扑。(以下每种拓扑适用于L4和L7负载平衡器)。

中间代理

图4:中间代理负载平衡拓扑

图4中所示的中间代理拓扑可能是获得大多数读者负载平衡的最熟悉的方法。此类别包括Cisco,Juniper,F5等硬件设备; 亚马逊的ALB和NLB以及谷歌的云负载均衡器等云软件解决方案和纯软件自托管解决方案,如HAProxyNGINXEnvoy中间代理解决方案的专家是用户简单性。通常,用户通过DNS连接到负载均衡器,无需担心其他任何问题。中间代理解决方案的一个问题是代理(即使是集群)是单点故障以及扩展瓶颈。中间代理通常也是黑盒子,使操作变得困难。客户端是否存在问题?在物理网络中?在中间代理?在后端?这很难说。

边缘代理

图5:边缘代理负载平衡拓扑

边缘代理拓扑如图5所示实际上只是中间代理拓扑的一种变体,可以通过Internet访问负载均衡器。在这种情况下,负载均衡器通常必须提供额外的“API网关”功能,例如TLS终止,速率限制,身份验证和复杂的流量路由。边缘代理的优缺点与中间代理相同。需要注意的是,在面向Internet的大型分布式系统中部署专用边缘代理通常是不可避免的。客户端通常需要使用服务所有者无法控制的任意网络库通过DNS访问系统(使以下部分中描述的嵌入式客户端库或sidecar代理拓扑不能直接在客户端上运行)。另外,

嵌入式客户端库

图6:通过嵌入式客户端库进行负载平衡

为了避免中间代理拓扑中固有的单点故障和扩展问题,更复杂的基础架构已经转向通过库将负载均衡器直接嵌入到服务中,如图6所示图书馆在支持的功能方面差异很大,但这一类中最知名且功能最丰富的一些是FinagleEureka / Ribbon / HystrixgRPC(松散地基于称为Stubby的内部Google系统)。基于库的解决方案的主要优势在于它将负载均衡器的所有功能完全分配给每个客户端,从而消除了先前描述的单点故障和扩展问题。基于库的解决方案的主要目标是,库必须以组织使用的每种语言实现。分布式架构正变得越来越“多语言”(多语言)。在这种环境下,以多种不同语言重新实现极其复杂的网络库的成本可能会变得令人望而却步。最后,在大型服务架构中部署库升级可能会非常痛苦,因此很可能会在生产中同时运行许多不同版本的库,

综上所述,上述图书馆已经成功地为那些能够限制编程语言扩散并克服库升级难度的公司提供了帮助。

边车代理

图7:通过sidecar代理进行负载平衡

嵌入式客户端库负载平衡器拓扑的变体是图7中所示的边车代理拓扑近年来,这种拓扑结构已经被推广为“服务网格”。边车代理背后的想法是,通过跳转到不同的进程而导致轻微的延迟损失,嵌入式库方法的所有好处都可以是没有任何编程语言锁定获得。在撰写本文时最受欢迎的边车代理负载均衡器是EnvoyNGINXHAProxyLinkerd有关边车代理方法的更详细的处理,请参阅我的博客文章介绍Envoy以及我的在服务网格数据平面与控制平面上发布

不同负载均衡器拓扑的总结和优缺点

  • 中间代理拓扑通常是最容易使用的负载平衡拓扑。由于单点故障,缩放限制和黑盒操作,它不足。
  • 边缘代理拓扑类似于中间代理,但通常无法避免。
  • 嵌入式客户端库拓扑提供了最佳性能和可伸缩性,但是需要以每种语言实现库以及跨所有服务升级库的需要。
  • sidecar代理拓扑的性能不如嵌入式客户端库拓扑,但不受任何限制。

总的来说,我认为sidecar代理拓扑(服务网格)正在逐步取代所有其他拓扑以进行服务到服务通信。在流量进入服务网格之前,始终需要边缘代理拓扑。

L4负载平衡的当前技术水平

L4负载平衡器是否仍然相关?

这篇文章已经讨论了L7负载平衡器对于现代协议的优势,并将在下面进一步详细介绍L7负载平衡器功能。这是否意味着L4负载平衡器不再相关?没有!虽然在我看来L7负载平衡器最终将完全取代用于服务到服务通信的 L4负载平衡器,但L4负载平衡器在边缘仍然非常相关因为几乎所有现代大型分布式架构都使用双层L4 / L7负载平衡架构用于互联网流量。在边缘部署中在L7负载平衡器之前放置专用L4负载平衡器的好处是:

  • 由于L7负载平衡器执行应用程序流量的更复杂的分析,转换和路由,因此它们可以处理相对较小部分的原始流量负载(以每秒数据包数和每秒字节数衡量),而不是优化的L4负载均衡器。这一事实通常使L4负载平衡器成为处理某些类型的DoS攻击(例如,SYN泛洪,通用数据包泛洪攻击等)的更好位置。
  • L7负载平衡器往往更积极地开发,更频繁地部署,并且比L4负载平衡器具有更多错误。在L7负载平衡器部署期间,前面有L4负载平衡器可以进行健康检查和排放,这比现代L4负载平衡器使用的部署机制要容易得多,后者通常使用BGP和ECMP(下面有更多内容)。最后,因为L7负载平衡器更容易出现缺陷,纯粹是由于其功能的复杂性,拥有可以绕过故障和异常的L4负载平衡器可以使整个系统更加稳定。

在下面的部分中,我将介绍中/边缘代理L4负载平衡器的几种不同设计。以下设计通常不适用于客户端库和边车代理拓扑。

TCP / UDP终端负载均衡器

图8:L4端接负载平衡器

仍在使用的第一种L4负载平衡器是终端负载平衡器,如图8所示这与我们在上面的L4负载平衡介绍中看到的负载均衡器相同。在这种类型的负载均衡器中,使用两个离散的TCP连接:一个在客户端和负载均衡器之间,一个在负载均衡器和后端之间。

L4终端负载平衡器仍然使用有两个原因:

  1. 它们实施起来相对简单。
  2. 对客户端的近距离(低延迟)连接终止具有重大的性能影响。具体地,如果终端负载平衡器可以靠近使用有损网络(例如,蜂窝网络)的客户端放置,则在数据被移动到可靠光纤传输到其最终位置之前,重传可能更快发生。换句话说,这种类型的负载平衡器可以在用于原始TCP连接终止的存在点(POP)场景中使用。

TCP / UDP直通负载均衡器

图9:L4直通负载平衡器

第二种L4负载平衡器是直通负载平衡器,如图9所示在这种类型的负载均衡器中,负载均衡器不会终止TCP连接而是在连接跟踪和网络地址转换(NAT)发生后,将每个连接的数据包转发到选定的后端首先,让我们定义连接跟踪和NAT:

  • 连接跟踪:是跟踪所有活动TCP连接状态的过程。这包括诸如握手是否已完成,是否已收到FIN,连接已空闲多长时间,已为连接选择了哪个后端等数据。
  • NAT:NAT是使用连接跟踪数据在数据包遍历负载均衡器时更改数据包的IP /端口信息的过程。

使用连接跟踪和NAT,负载均衡器可以通过从客户端到后端的大多数原始TCP流量。例如,假设客户端正在与之通信,1.2.3.4:80并且所选择的后端位于10.0.0.2:9000客户端TCP数据包将到达负载均衡器1.2.3.4:80然后,负载均衡器将交换数据包的目标IP和端口10.0.0.2:9000它还将交换数据包的源IP和负载均衡器的IP地址。因此,当后端响应TCP连接时,数据包将返回负载均衡器,在负载均衡器中发生连接跟踪,NAT可以反向再次发生。

为什么使用这种类型的负载平衡器代替上一节中描述的终端负载平衡器,因为它更复杂?原因如下:

  • 性能和资源使用情况:由于直通负载均衡器不会终止TCP连接,因此它们不需要缓冲任何TCP连接窗口。每个连接存储的状态量非常小,通常通过有效的哈希表查找来访问。因此,直通负载平衡器通常可以处理比终止负载平衡器大得多的活动连接数和每秒数据包数(PPS)。
  • 允许后端执行自定义拥塞控制TCP拥塞控制是Internet上端点限制发送数据以便不会压倒可用带宽和缓冲区的机制。由于直通负载均衡器未终止TCP连接,因此它不参与拥塞控制。这一事实允许后端根据其应用用例使用不同的拥塞控制算法。它还允许更容易地进行拥塞控制变更的实验(例如,最近的BBR推出)。
  • 形成直接服务器返回(DSR)和集群L4负载平衡的基线:更高级的L4负载平衡技术(例如DSR和具有分布式一致性散列的集群)需要直通负载平衡(将在以下各节中讨论)。

直接服务器返回(DSR)

图10:L4直接服务器返回(DSR)

直接服务器返回(DSR)负载均衡器如图10所示DSR建立在上一节中描述的直通负载均衡器之上。DSR是一种优化,其中只有入口/请求数据包遍历负载均衡器。出口/响应数据包在负载均衡器周围直接返回客户端。执行DSR有趣的主要原因是,在许多工作负载中,响应流量使请求流量相形见绌(例如,典型的HTTP请求/响应模式)。假设10%的流量是请求流量,90%的流量是响应流量,如果DSR正在使用1/10的负载均衡器容量可以满足系统的需要。由于历史上负载平衡器非常昂贵,因此这种类型的优化会对系统成本和可靠性产生重大影响(总是更好)。DSR负载平衡器扩展了直通负载均衡器的概念,具体如下:

  • 负载平衡器通常仍执行部分连接跟踪。由于响应数据包不会遍历负载均衡器,因此负载均衡器将不会知道完整的TCP连接状态。但是,负载均衡器可以通过查看客户端数据包和使用各种类型的空闲超时来强烈推断状态。
  • 负载均衡器通常使用通用路由封装(GRE)来封装从负载均衡器发送到后端的IP数据包,而不是NAT 因此,当后端接收封装的数据包时,它可以对其进行解封装并知道客户端的原始IP地址和TCP端口。这允许后端直接响应客户端,而响应数据包不会流经负载均衡器。
  • DSR负载均衡器的一个重要部分是后端参与负载均衡后端需要具有正确配置的GRE隧道,并且根据网络设置的低级细节可能需要其自己的连接跟踪,NAT等。

请注意,在直通负载均衡器和DSR负载均衡器设计中,可以通过负载均衡器和后端设置连接跟踪,NAT,GRE等多种方式。不幸的是,该主题超出了本文的范围。

通过高可用性对实现容错

图11:通过HA对和连接跟踪的L4容错

到目前为止,我们一直在考虑单独设计L4负载平衡器。passthrough和DSR负载均衡器都需要在负载均衡器本身中进行一定量的连接跟踪和状态。如果负载均衡器死了怎么办?如果负载平衡器的单个实例死亡,则将切断遍历负载平衡器的所有连接。根据应用程序的不同,这可能会对应用程序性能产生重大影响。

从历史上看,L4负载平衡器是从典型供应商(Cisco,Juniper,F5等)购买的硬件设备。这些设备非常昂贵并且处理大量流量。为了避免单个负载平衡器故障切断所有连接并导致严重的应用程序中断,负载平衡器通常部署在高可用性对中,如图11所示典型的HA负载平衡器设置具有以下设计:

  • 一对HA边缘路由器服务于一定数量的虚拟IP(VIP)。这些边缘路由器使用边界网关协议(BGP宣告VIP 主边缘路由器的BGP权重高于备份,因此在稳定状态下,它为所有流量提供服务。(BGP是一个极其复杂的协议;出于本文的目的,只考虑BGP一种机制,通过该机制,网络设备宣布它们可用于从其他网络设备获取流量,并且每个链路可以具有优先考虑链路流量的权重)。
  • 类似地,主L4负载均衡器向具有比备份更高的BGP权重的边缘路由器宣告自己,因此在稳定状态下它正在为所有流量服务。
  • 主负载均衡器交叉连接到备份,并共享其所有连接跟踪状态。因此,如果主模块死亡,则备份可以接管处理所有活动连接。
  • 两个边缘路由器和两个负载平衡器都是交叉连接的这意味着如果其中一个边缘路由器或其中一个负载平衡器死亡,或者由于某些其他原因而撤销其BGP通知,则备份可以接管所有流量。

上面的设置是今天仍然有多少高流量的互联网应用程序。但是,上述方法存在很大的缺点:

  • 考虑到容量使用情况,必须在HA负载均衡器对之间正确分片VIP。如果单个VIP增长超过单个HA对的容量,则VIP需要分成多个VIP。
  • 系统的资源使用率很低。50%的容量处于稳定状态。鉴于历史上硬件负载平衡器非常昂贵,这导致大量闲置资本。
  • 现代分布式系统设计比主动/备份提供更好的容错能力。例如,最佳地,系统应该能够遭受多个同时发生的故障并继续运行。如果活动和备份负载平衡器同时死亡,则HA负载平衡器对容易发生完全故障。
  • 供应商提供的专有大型硬件设备非常昂贵,导致供应商锁定。通常希望用使用商用计算服务器构建的水平可扩展软件解决方案来替换这些硬件设备。

通过具有分布式一致性散列的集群进行容错和扩展

图12:通过集群负载平衡器和一致性散列的L4容错和扩展

上一节介绍了通过HA对的L4负载均衡器容错以及该设计中固有的问题。从2000年代早期到中期,大型互联网基础设施开始设计和部署新的大规模并行L4负载平衡系统,如图12所示这些系统的目标是:

  • 减轻上一节中描述的HA对设计的所有缺点。
  • 从供应商的专有硬件负载平衡器转向使用标准计算服务器和NIC构建的商品软件解决方案。

此L4负载平衡器设计最好称为容错和通过群集和分布式一致性散列进行扩展它的工作原理如下:

  • N个边缘路由器以相同的BGP权重宣布所有Anycast VIP。等价多路径路由(ECMP)用于确保通常来自单个流的所有分组到达相同的边缘路由器。流通常是源IP /端口和目标IP /端口的4元组。(简而言之,ECMP是一种使用一致哈希在一组相同加权的网络链路上分发数据包的方法)。虽然边缘路由器本身并不特别关心哪些分组到达那里,但是通常优选的是来自流的所有分组遍历同一组链路,以避免乱序性能降低性能的分组。
  • N L4负载均衡器机器以与边缘路由器相同的BGP权重通告所有VIP。再次使用ECMP,边缘路由器通常会为流选择相同的负载平衡器机器。
  • 每个L4负载均衡器机器通常会执行部分连接跟踪,然后使用一致性散列来选择流的后端。GRE用于封装从负载均衡器发送到后端的数据包。
  • 然后,DSR用于通过边缘路由器将数据包直接从后端发送到客户端。
  • L4负载均衡器使用的实际一致性哈希算法是一个活跃的研究领域。在权衡负载,最小化延迟,最小化后端更改期间的中断
    以及最小化内存开销方面存在权衡对该主题的完整讨论超出了本文的范围。

让我们看看上述设计如何减轻HA对方法的所有缺点:

  • 可根据需要添加新的边缘路由器和负载平衡器。在添加新计算机时,每层都使用一致的哈希来尽可能减少受影响流的数量。
  • 系统的资源使用可以根据需要运行,同时保持足够的突发容限和容错。
  • 边缘路由器和负载平衡器现在都可以使用商用硬件构建,而成本只是传统硬件负载平衡器的一小部分(下面将详细介绍)。

通常被问到这个设计的一个问题是“边缘路由器为什么不通过ECMP直接与后端通信?为什么我们需要负载均衡器?“其原因主要是围绕DoS缓解和后端操作简便性。如果没有负载均衡器,每个后端都必须参与BGP,并且执行滚动部署的难度要大得多。

所有现代L4负载平衡系统都在朝着这种设计(或其某些变体)发展。最着名的两个例子是Google的Maglev亚马逊网络负载均衡器(NLB)目前没有任何OSS负载均衡器可以实现这种设计,但是,我知道有一家公司计划在2018年向OSS发布一个。我对这个版本感到非常兴奋,因为现代L4负载均衡器是一个至关重要的部分在网络空间中缺少OSS。

L7负载平衡的当前技术水平

确实是的。最近几年L7负载均衡器/代理开发出现了复苏。这与分布式系统中对微服务架构的持续推动非常吻合。从根本上说,当更频繁地使用时,固有故障的网络变得更难以有效地操作。此外,自动扩展,容器调度程序等的兴起意味着在静态文件中供应静态IP的日子早已不复存在。系统不仅更多地利用网络,它们变得更加动态,需要负载平衡器中的新功能。在本节中,我将简要总结现代L7负载平衡器中发展最多的领域。

协议支持

现代L7负载平衡器正在为许多不同的协议添加明确的支持。负载均衡器对应用流量的了解越多,它在可观察性输出,高级负载平衡和路由等方面就可以做得越复杂。例如,在撰写本文时,Envoy明确支持L7协议解析和路由。对于HTTP / 1,HTTP2,gRPC,Redis,MongoDB和DynamoDB。未来可能会添加更多协议,包括MySQL和Kafka。

动态配置

如上所述,分布式系统的日益动态的性质需要在创建动态和反应控制系统方面进行并行投资。Istio就是这种系统的一个例子。有关此主题的更多信息,请参阅我在服务网格数据平面与控制平面上的帖子

高级负载平衡

L7负载平衡器现在通常内置支持高级负载平衡功能,如超时,重试,速率限制,断路,阴影,缓冲,基于内容的路由等。

观测

如上面关于一般负载平衡器功能的部分所述,正在部署的越来越动态的系统变得越来越难以调试。强大的协议特定可观察性输出可能是现代L7负载平衡器提供的最重要的功能。现在,任何L7负载平衡解决方案几乎都需要输出数字统计,分布式跟踪和可自定义日志记录。

可扩展性

现代L7负载平衡器的用户通常希望轻松扩展它们以添加自定义功能。这可以通过编写加载到负载均衡器中的可插入过滤器来完成。许多负载平衡器也支持脚本,通常通过Lua

容错

我写了很多关于L4负载均衡器容错的文章。L7负载均衡器容错怎么样?通常,我们将L7负载平衡器视为可消耗和无状态的。使用商用软件可以轻松地水平缩放L7负载平衡器。此外,L7负载平衡器执行的处理和状态跟踪比L4复杂得多。尝试建立L7负载均衡器的HA配对在技术上是可行的,但这将是一项重大任务。

总的来说,在L4和L7负载均衡域中,业界正逐渐从HA配对转向通过一致散列融合的水平可扩展系统。

和更多

L7负载平衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述

全局负载均衡和集中控制平面

图13:全局负载平衡

负载平衡的未来将越来越多地将各个负载平衡器视为商品设备。在我看来,真正的创新和商业机会都在控制平面内。图13显示了全局负载平衡系统的示例在这个例子中,发生了一些不同的事情:

  • 每个边车代理与三个不同区域(A,B和C)中的后端通信。
  • 如图所示,90%的流量被发送到区域C,而5%的流量被发送到区域A和B.
  • sidecar代理和后端都向全局负载均衡器报告周期性状态。这允许全局负载平衡器做出考虑延迟,成本,负载,当前故障等的决策。
  • 全局负载平衡器周期性地为每个边车代理配置当前路由信息。

全局负载均衡器将越来越能够完成任何单个负载均衡器无法独立完成的复杂事物。例如:

  • 自动检测并绕过区域性故障。
  • 应用全局安全和路由策略。
  • 使用机器学习和神经网络检测和缓解包括DDoS攻击在内的流量异常。
  • 提供集中的UI和可视化,使工程师能够聚合地理解和操作整个分布式系统。

为了实现全局负载平衡,用作数据平面的负载平衡器必须具有复杂的动态配置功能。有关此主题的更多信息,请参阅我在Envoy的通用数据平面API以及服务网格数据平面与控制平面帖子

从硬件到软件的演变

到目前为止,这篇文章仅简要提到了硬件与软件,主要是在历史L4负载均衡器HA对的上下文中。这个领域的行业趋势是什么?

之前的推文是一种幽默的夸张,但仍然总结了很多趋势,它们是:

  • 从历史上看,路由器和负载平衡器已被提供为极其昂贵的专有硬件。
  • 越来越多的大多数专有L3 / L4网络设备正在被商用服务器硬件,商用NIC以及基于IPVSDPDKfd.io等框架构建的专用软件解决方案所取代成本低于5千美元的现代数据中心机器可以使用Linux和使用DPDK编写的自定义用户空间应用程序轻松地使用非常小的数据包使80Gbps网卡饱和。与此同时,能够以惊人的总带宽和数据包速率进行ECMP路由的廉价且基本的路由器/交换机ASIC被打包为商品路由器。
  • 复杂的L7软件负载平衡器,如NGINX,HAProxy和Envoy,也在快速迭代和侵占之前的F5等供应商领域。因此,L7负载平衡器也在积极地转向商用软件解决方案。
  • 与此同时,整个行业向主要云提供商推动IaaS,CaaS和FaaS的转变意味着越来越少的工程师需要了解物理网络的工作原理(这些是“黑魔法“和”我们不再需要知道蹲下的“上面的部分”。

结论和负载平衡的未来

总而言之,这篇文章的主要内容是:

  • 负载平衡器是现代分布式系统中的关键组件。
  • 有两种通用类型的负载平衡器:L4和L7。
  • L4和L7负载平衡器都与现代架构相关。
  • L4负载平衡器正朝着可水平扩展的分布式一致性散列解决方案发展。
  • 由于动态微服务架构的激增,L7负载平衡器最近投入巨资。
  • 全局负载平衡以及控制平面和数据平面之间的分离是负载平衡的未来,并且可以找到大多数未来的创新和商业机会。
  • 该行业正在积极地转向用于网络解决方案的商用OSS硬件和软件。我相信像F5这样的传统负载平衡供应商将首先被OSS软件和云供应商所取代。传统路由器/交换机供应商,如Arista / Cumulus /等。我认为在内部部署方面有更大的发展,但最终也将被公共云供应商和他们自己开发的物理网络取代。

总的来说,我认为这是计算机网络的一个迷人时刻!大多数系统向OSS和软件的转变正在将迭代速度提高几个数量级。此外,随着分布式系统通过“无服务器”范例继续向动态迈进,底层网络和负载平衡系统的复杂性将需要相应增加。

使用nginx配置多个php-fastcgi负载均衡

配置还是非常简单的,充分体现了nginx的强大与配置的简单。

应用的最前端是一台nginx服务器,所有静态的内容都由nginx来处理,而将所有php的 请求都分摊到下游的若干台

运行PHP fastcgi守护进程的服务器中,这样可以以一种廉价的方案来实现对系统负载的分摊,扩展系统的负载能力。

三台php-fastcgi服务器的ip地址分别为:

          172.16.236.110 ,   172.16.236.111,     172.16.236.112

运行php-fastcgi进程时,需要让php-cgi监听到服务器的局域网地址(分别如上所示),而不是之前一般都是监听的

本地地址(127.0.0.1)。

以 172.16.236.110这台服务器为例:

 
/usr/local/php5/bin/php-cgi -b 172.16.236.110:9000

或许你用spawn-fcgi来启动php-fcgi,那么就是这样(供参考,其实也就是修改监听的地址和端口即可):

 
/usr/local/lighttpd/bin/spawn-fcgi -f /usr/local/php5/bin/php-cgi -a 172.16.236.110 -p 9000

又或许你是用php-fpm来管理php-fcgi,那么你需要修改php-fpm的配置:

 
vim  /usr/local/php5/etc/php-fpm.conf

找到这个配置项(其中的地址可能需要根据你自己环境来调整)



<value< span=”” style=”word-wrap: break-word;”> name=”listen_address“>127.0.0.1:9000>

修改为:

<value< span=”” style=”word-wrap: break-word;”> name=”listen_address>172.16.236.110:9000>



修改完毕后,重启你的php-fpm进程。

然后按照上面的步骤,依次修改其他php fastcgi服务器。

php方面的工作暂时就是这些,下面修改nginx。

 
vim  /usr/local/nginx/conf/nginx.conf

在配置文件的http段内增加类似如下的配置:

1
2
3
4
5
upstream myfastcgi { server 172.16.236.110 weight=1; server 172.16.236.111 weight=1; server 172.16.236.112 weight=1; }

我这里三台php fastcgi服务器的权重是相同的,所以其中的weight值都是1,如果你的php fastcgi服务器需要分主次,那么

可以通过调整其weight值来达到目的。比如以第一台服务器为主,其他两台为辅,则就是这样:

1
2
3
4
5
upstream myfastcgi { server 172.16.236.110 weight=1; server 172.16.236.111 weight=2; server 172.16.236.112 weight=2; }

然后找到原来nginx关于php fastcgi配置的部分,比如:

1
2
3
4
5
6
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

将其中的fastcgi_pass那一段改为:



fastcgi_pass myfastcgi;

其中的myfastcgi也就是上面刚刚配置的php fastcgi均衡器的名字了。

完了以后,重启nginx即可。

简单吧,就通过这么几个简单的配置,就可以实现一个经济高效的nginx、多php-fcgi的负载均衡解决方案了。

当然了,这样的方案运用到实际项目中 还需要进行一些细化的配置,主要是php方面还需要进一步配置

Nginx负载均衡的优缺点

Nginx的优点是:
1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
2、Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点本人深有体会;
3、Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。
3、可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。
4、Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
5、Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。
6、Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。
7、Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。
8、Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。
淘宝的前端使用的Tengine就是基于nginx做的二次开发定制版。
  Nginx的缺点是:
1、Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。
2、对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测不支持Session的直接保持,但能通过ip_hash来解决