负载均衡入门

709 阅读7分钟

1. 什么是负载均衡

  • 负载均衡(Load Balancing)是一种将网络流量、请求或工作负载分配到多个服务器或计算资源上的技术。其目的是提高系统的性能、可靠性和可扩展性
  • 在一个高流量或高负载的网络环境中,单个服务器可能无法处理所有的请求或工作负载。负载均衡通过将流量分发到多个服务器上,使得每个服务器都能够平均分担负载,从而提高整个系统的处理能力

2. 负载均衡的实现方式

  • 基于网络层的负载均衡:通过在网络层(如路由器、交换机)上进行流量分发,将请求分发到不同的服务器上。常见的协议有基于IP的负载均衡(如Round Robin、Least Connections)和基于DNS的负载均衡(如DNS轮询、DNS解析返回多个IP地址)

  • 基于应用层的负载均衡:通过在应用层(如负载均衡设备、反向代理服务器)上进行流量分发,根据请求的内容、协议或其他特征将请求分发到不同的服务器上。常见的协议有HTTP、HTTPS、SMTP等

3. 负载均衡策略

集中式LB

  • 集中式LB方案,如下图。首先,服务的消费方与提供方不直接耦合,而是在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx)

  • LB上有所有服务的地址映射表,通常由运维配置注册。当服务消费方调用某个目标服务的时候,先向LB发起请求,由LB以某种策略(比如Round-Robin)做负载均衡后将请求转发到目标服务

  • LB一般具有健康检查能力,能自动摘除不健康的服务实例

  • 服务消费方如何发现LB呢?

    • 通常的做法是通过DNS,运维人员为服务配置一个DNS域名,这个域名指向LB。这种方案基本可以否决,因为它有致命的缺点:所有服务调用流量都经过load balance服务器,所以load balace服务器成了系统的单点,一旦LB发生故障对整个系统的影响是灾难性的
    • 为了解决这个问题,必然需要对这个load balance部件做分布式处理(部署多个实例、冗余,然后解决一致性问题等全家桶解决方案),但这样做会徒增非常多的复杂度

进程内LB

  • 进程内的Load Balance:将Load Balance的功能和算法全部以sdk的方式实现在客户端进程内。如下图:

  • 可以看到,引入了第三方:服务注册中心。它做两件事:

    • 维护服务提供的方的节点列表,并检查这些节点的健康度。每个节点部署成功,都通知注册中心;然后一直和注册中心保持心跳
    • 允许服务调用方注册感兴趣的事件,把服务提供方的变化情况推送到服务的调用方
  • 这种方案下,整个Load Balance的调用过程是这样的:

    • 服务注册中心维护所有节点的情况
    • 任何一个节点想要订阅其他服务方提供的节点列表,向服务注册中心注册
    • 服务注册中心将服务方提供的节点列表(以长连接的方式)推送到消费方
    • 消费方收到消息后,在本地维护一份这个列表,并自己做Load Balance

可见,服务注册中心充当什么角色?

它是唯一一个知道整个集群内部所有的节点情况的中心。 所以对它的可用性要求会非常高,这个组件可以用Zookeeper实现。

这种方案的缺点是:每个语言都要研究一套sdk,如果公司内的服务使用的语言五花八门的话,这方案的 成本会很高。第二点是:后续如果要对客户库进行升级,势必要求服务调用方修改代码并重新发布,所以 该方案的升级推广有不小的阻力。

独立进程LB

该方案是针对第二种方案的不足提出的一种折中方案,原理和第二种方案基本类似,不同之处是,它将LB和服务发现功能从进程内移出来,变成主机上的一个独立进程,主机上的一个或者多个服务要访问目标服务时,他们都通过同一主机上的独立LB进程做服务发现和负载均衡(简单的理解就是,将LB也部署成服务)。如下图:

这个方案解决上一种方案的问题,不需要为不同语言开发用户库,LB升级不需要服务调用方修改代码;但引入新的问题是 —— 这个组件本身的可用性谁来维护?还要再写一个watchdog去监控这个组件吗?另外,多了一个环节,就多了一个出错的可能,线上出问题了,也多了一个需要维护的环节

grpc负载均衡策略

4. 负载均衡原理

负载均衡的原理可以分为两个方面:流量分发和健康检查

  • 流量分发:负载均衡器接收到来自客户端的请求后,需要将请求分发到多个服务器上。常见的负载均衡算法有以下几种:

    • 轮询(Round Robin):按照请求的先后顺序将用户请求循环地分配到每台服务器。
    • 加权轮询(Weighted Round Robin):根据服务器的权重设置,将请求按照权重比例分发给不同的服务器。
    • 最少连接(Least Connection):将请求分发给当前连接数最少的服务器。
    • 哈希( Hash):基于URI、 HOST、SRC_IP、IP+PORT的哈希算法,将包含不同元素的用户访问尽可能地平均调度到服务器集群中的各台服务器上。
    • 优先级(Priority):将服务器按优先级分组,优先调度优先级高的,只有优先级高的服务器发生故障,才调度优先级低的服务器。
  • 健康检查:负载均衡器需要定期检查后端服务器的健康状态,以确保只将请求分发给可用的服务器。常见的健康检查方式有以下几种:

    • 心跳检测(Heartbeat):负载均衡器定期向后端服务器发送心跳请求,检测服务器是否正常响应。
    • 响应超时检测:负载均衡器设置一个合理的响应超时时间,如果服务器在规定时间内没有响应,则认为服务器不可用。
    • 负载检测:负载均衡器通过监控服务器的负载情况,如CPU利用率、内存使用率等,判断服务器的可用性。

当负载均衡器接收到请求后,根据负载均衡算法选择一个可用的服务器,并将请求转发给该服务器。服务器处理完请求后,将响应返回给负载均衡器,再由负载均衡器将响应返回给客户端。

通过流量分发和健康检查的组合,负载均衡器可以实现将请求均匀地分发到多个服务器上,并确保只将请求发送给可用的服务器,从而提高系统的性能、可靠性和可扩展性。