架构设计:负载均衡层设计方案(8)——负载均衡层总结上篇

2018/6/28 posted in  Network

https://blog.csdn.net/yinwenjie/article/details/47211641

1、概述

很明显通过前面的八篇文章的介绍,并不能覆盖负载均衡层的所有技术,但是可以作为一个引子,告诉各位读者一个学习和使用负载均衡技术的思路。虽然后面我们将转向 “业务层” 和“业务通信”层的介绍,但是对负载均衡层的介绍也不会停止。在后续的时间我们将穿插进行负载均衡层的新文章的发布,包括 Nginx 技术的再介绍、HaProxy、LVS 新的使用场景等等。

这篇文章我们对前面的知识点进行总结,并有意进行一些扩展,以便于各位读者找到新的学习思路。

2、负载均衡层的核心思想

2-1、一致性哈希与 Key 的选取

《架构设计:负载均衡层设计方案(2)——Nginx 安装》 文章中我们详细介绍了一致性哈希算法。并且强调了一致性 Hash 算法是现代系统架构中的最关键算法之一,在分布式计算系统、分布式存储系统、数据分析等众多领域中广泛应用。针对我的博文,在负载均衡层、业务通信层、数据存储层都会有它的身影。

一致性算法的核心是:

  • 使用对象的某一个属性(这个属性可以是服务器的 IP 地址、开放端口 还可以是用户名、某种加密串。凡是你可以想到的有散列意义的属性),算出一个整数,让其分布在 0 至 2 的 32 次方 范围内。
  • 一台服务器的某个或者某一些属性当然也可以进行 hash 计算,并且根据计算分布在这个圆环上的某一个点,也就是图中圆环上的蓝色点。
  • 一个处理请求到来时,根据这个请求的某一个或者某一些属性进行 hash 计算,并且根据计算记过分布在这个圆环上的某一个点上。也就是上图圆环上的黄色点。
  • 我们约定落在某一个蓝点 A 左侧和蓝点 B 右侧的黄色点所代表的请求,都有蓝点 A 所代表的服务器进行处理,这样就完成解决了 “谁来处理” 的问题。在蓝色点稳定存在的前提下,来自于同一个 Hash 约定的请求所落在的位置都是一样的,这就保证了服务处理映射的稳定性。
  • 当某一个蓝色点由于某种原因下线,其所影响到的黄色点也是有限的。即下一次客户端的请求将由其他的蓝色点所代表的服务器进行处理。

2-2、轮询与权

  • 不加权轮询,就是主控节点(任务来源点)在不考虑目标节点的任何因素的情况下(例如 CPU 性能、磁盘性能、网络性能),按照目标节点的列表顺序将任务依次分配下去。这是最简单的轮询,也是对主控节点实现复杂性要求最低的轮询。我之前的博文《架构设计:负载均衡层设计方案(2)——Nginx 安装》《架构设计:负载均衡层设计方案(4)——LVS 原理》 都对这种最简轮询进行了介绍:例如 LVS 中的 “rr” 参数。

  • 加权轮询中的 “权”,您可以看成是“轮询” 依据的意思。“权”可以是很多种可能,可以是目标机器的性能量化值、可以是一个固定的数字(按照固定数字加权)、可以是目标节点的网络速度。例如 LVS 中的 “lc” 参数,就是指按照目标机器,现在已有的 “连接” 数量进行加权:连接数量越少,越有更大的几率获得这个任务的处理权。

2-3、租约与健康检查

租约协议主要为了保证一个事实:如果服务器对客户端的检查操作在 “最迟时间” 失败后,那么服务器端肯定会注销客户端的登录信息,同时客户端上服务器的连接信息也会消失(并且不在向下提供服务)。每一次检查成功,这个 “最迟时间” 都会向后推移。

租约协议和我们提到的哈希算法一下一样,也是系统架构设计中最基本的设计思想,并且大量运用在各类型的系统中,它的工作原理是每一位架构师都需要掌握的。例如:zookeeper 使用这个协议保证 Flow 节点和 Leader 节点的链路是正常的;分布式存储系统用这个协议保证 datanode 和 namenode 的连接是正常的;

3、负载均衡层技术汇总

在前面的博文中,我重点介绍了 Nginx、LVS、Keepalived 技术。由于时间有限,这里我们对博文中提到的几种技术进行一个总结,然后再扩展介绍一下 DNS 技术、CDN 技术和硬件负载技术。

3-1、Nginx 技术

在负载均衡层这个大的章节中,我有三篇文章都在直接介绍 Nginx 的原理和使用。但是之后有朋友给我反映还想了解更多的 Nginx 知识,特别点名要求我再做一篇文章介绍 Nginx 的动态缓存。是的,我在后面的时间里是有计划介绍 Nginx 的动态缓存技术,还会介绍 Nginx 和多款主流的反向代理软件的性能对比。但这需要时间,特别是我不想去网上找一些已有的性能对比图,还是自己一边做这样的性能测试,一边做性能报告比较靠谱。

下面这些技术是我在博文中已经重点介绍过得,我们再做一下总结:

  • Nginx 中的连接数限制问题

重要的配置项包括:worker_processes、worker_connections。但是光是配置这些属性是不够的,最关键的是我们要打开操作系统级别的 “最大文件数” 限制问题。使用 “ulimit -n 65535” 设置本次会话的 “最大文件数” 限制;还要使用 “vim /etc/security/limits.conf” 命令,修改内核的配置信息。主要是以下两项:

* soft nofile 65535 
* hard nofile 65535

另外,还要注意和 nginx 配置项中的 “worker_rlimit_nofile” 属性共同使用:

user root root; 
worker_processes 4; 
worker_rlimit_nofile 65535;

#error_log logs/error.log; 
#error_log logs/error.log notice; 
#error_log logs/error.log info;

#pid logs/nginx.pid; 
events { 
    use epoll; 
    worker_connections 65535; 
}
  • Nginx 中的 Gzip 技术

gzip 是 Nginx 进行 HTTP Body 数据压缩的技术。下面这段 Nginx 配置信息是启用 gzip 压缩的实例:

#开启gzip压缩服务, 
gzip on;

#gzip压缩是要申请临时内存空间的,假设前提是压缩后大小是小于等于压缩前的。例如,如果原始文件大小为10K,那么它超过了8K,所以分配的内存是8 * 2 = 16K;再例如,原始文件大小为18K,很明显16K也是不够的,那么按照 8 * 2 * 2 = 32K的大小申请内存。如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。 
gzip_buffers 2 8k;

#进行压缩的原始文件的最小大小值,也就是说如果原始文件小于5K,那么就不会进行压缩了 
gzip_min_length 5K;

#gzip压缩基于的http协议版本,默认就是HTTP 1.1 
gzip_http_version 1.1;

# gzip压缩级别1-9,级别越高压缩率越大,压缩时间也就越长CPU越高 
gzip_comp_level 5;

#需要进行gzip压缩的Content-Type的Header的类型。建议js、text、css、xml、json都要进行压缩;图片就没必要了,gif、jpge文件已经压缩得很好了,就算再压,效果也不好,而且还耗费cpu。 
gzip_types text/HTML text/plain application/x-javascript text/css application/xml;

http 返回数据进行压缩的功能在很多场景下都实用:

a、 如果浏览器使用的是 3G/4G 网络,那么流量对于用户来说就是 money。

b、 压缩可节约服务器机房的对外带宽,为更多用户服务。按照目前的市场价良好的机房带宽资源的一般在 200RMB/Mbps,而服务器方案的压力往往也来自于机房带宽。

c、 不是 Nginx 开启了 gzip 功能,HTTP 响应的数据就一定会被压缩,除了满足 Nginx 设置的 “需要压缩的 http 格式” 以外,客户端(浏览器)也需要支持 gzip(不然它怎么解压呢),一个好消息是,目前大多数浏览器和 API 都支持 http 压缩。

  • Nginx 中的 rewrite(重写)技术

Nginx 的强大在于其对 URL 请求的重写(重定位)。Nginx 的 rewrite 功能依赖于 PCRE Lib,请一定在 Nginx 编译安装时,安装 Pcre lib。

Nginx 的 rewrite 功能在我《架构设计:负载均衡层设计方案(3)——Nginx 进阶》 这边博客中进行了讲解。

下面是一段 rewrite 的示例:

#示例1:
location ~* ^/(.+)/(.+)\.(jpg|gif|png|jpeg)$ {
    rewrite ^/orderinfo/(.+)\.(jpg|gif|png|jpeg)$   /img/$1.$2   break;
    root   /cephclient;
}

#location在不进行大小写区分的情况下利用正则表达式对$url进行匹配。当匹配成功后进行rewrite重定位。
#rewrite进行重写url的规则是:regex表达式第一个括号中的内容对应$1,regex表达式第二个括号中的内容对应$2,以此类推。
#这样重定位的意义就很明确了:将任何目录下的文件名重定位到img目录下的对应文件名,
#并且马上在这个location中(注意是Nginx,而不是客户端)执行这个重写后的URL定位。

#示例2:
server {
    。。。。
    。。。。
    location ~* ^/orderinfo/(.+)\.(jpg|gif|png|jpeg)$ {
        rewrite ^/orderinfo/(.+)\.(.+)$  /img/$1.$2   last;
    }

    location / {
        root   /cephclient;
    }
}

#在server中,有两个location位置,当url需要访问orderinfo目录下的某一个图片时,rewrite将重写这个url,
#并且重新带入这个url到server执行,这样“location /”这个location就会执行了,并找到图片存储的目录。
  • Nginx 的图片处理模块

http_image_filter_module 是 nginx 的图片处理模块,是使用 nginx 进行静态资源和动态资源分开管理的关键引用技术。通过这个模块可以对静态资源进行缩放、旋转、验证。

需要注意的是,http_image_filter_module 模块所处理的缩率图片是不进行保存的,完全使用节点的 CPU 性能进行计算,使用节点的内存进行临时存储。所以如果要使用 http_image_filter_module 进行图片处理,一定要根据客户端的请求规模进行 nginx 节点的调整。并且当站点的 PV 达到一定的规模时,一定要使用 CDN 技术进行访问加速、对图片的访问处理手段进行规划。

由于我们在之前涉及 Nginx 的文章中,并没有详细讲解 Nginx 的图片处理模块,只是说了要进行介绍,所以这里我给出一个较为详细的安装和配置示例:

nginx 的 http_image_filter_module 模块由 GD library 进行支持,所以要使用这个图片处理模块,就必须进行第三方依赖包的安装:

yum install gd-devel

然后,Nginx 要进行重新编译:

configure --with-http_image_filter_module
make && make install

使用图片处理模块的配置示例:

location ~* /(.+)_(\d+)_(\d+)\.(jpg|gif|png|ioc|jpeg)$ {
    set $h $3;
    set $w $2;
    rewrite /(.+)_(\d+)_(\d+)\.(jpg|gif|png|ioc|jpeg)$ /$1.$4 break;

    image_filter resize $w $h;
    image_filter_buffer 2M;
}

其中关于正则表达式的语法和已经介绍过的 rewrite 的语法就不再进行介绍了,主要看 http_image_filter_module 相关的属性设置:

image_filter test:测试图片文件合法性
image_filter rotate:进行图片旋转,只能按照 90 | 180 | 270 进行旋转
image_filter size:返回图片的 JSON 数据
image_filter resize width height:按比例进行图片的等比例缩小,注意,是只能缩小,第二缩小是等比例的。
image_filter_buffer:限制图片最大读取大小,没有设置就是 1M;根据不同的系统最好设置为 2M—3M
image_filter_jpeg_quality:设置 jpeg 图片的压缩比例(1-99,越高越好)
image_filter_transparency:禁用 gif 和 png 图片的透明度。

  • 和 Nginx 类似的其他技术 / 软件

目前行业内也有很多与 Nginx 解决同类问题的软件,他们分别是 Apache 基金会的 Apache HTTP Server、淘宝开源的 Tengine、Haproxy、包括 Windows 下运行的 IIS,也支持反向代理 。

这里笔者再次重点提到 Tengine,建议各位读者有时间的时候可以使用一下,这个对 Nginx 进行了深度再开发的软件。

3-2、LVS 技术

LVS 是 Linux Virtual Server 的简写,意即 Linux 虚拟服务器,是一个虚拟的服务器集群系统。本项目在 1998 年 5 月由章文嵩博士成立。

LVS 集群采用 IP 负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。

在我的系列文章中,《架构设计:负载均衡层设计方案(4)——LVS 原理》《架构设计:负载均衡层设计方案(5)——LVS 单节点安装》《负载均衡层设计方案(7)——LVS + Keepalived + Nginx 安装及配置》 都涉及到 LVS 的讲解。

这里我们再总结一下 LVS 中的三种工作模式:

3-2-1、NAT 模式

NAT 方式是一种由 LVS Master 服务节点收到数据报,然后转给下层的 Real Server 节点,当 Real Server 处理完成后回发给 LVS Master 节点然后又由 LVS Master 节点转发出去的工作方式。LVS 的管理程序 IPVSADMIN 负责绑定转发规则,并完成 IP 数据报文和 TCP 数据报文中属性的重写。

LVS-NAT 模式的优点在于:

  • 配置管理简单。LVS-NAT 的工作方式是 LVS 三种工作模式中最容易理解、最容易配置、最容易管理的工作模式。

  • 节省外网 IP 资源,一般机房分配给使用者的 IP 数量是有限的,特别是您购买的机架的数量不多时。LVS-NAT 工作方式将您的系统架构封装在局域网中,只需要 LVS 有一个外网地址或外网地址映射就可以实现访问了。

  • 系统架构相对封闭。在内网环境下我们对防火墙的设置要求不会很高,也相对容易进行物理服务器的运维。您可以设置来源于外网的请求需要进行防火墙过滤,而对内网请求开放访问。

  • 另外改写后转给 Real Server 的数据报文,Real Server 并不会关心它的真实性,只要 TCP 校验和 IP 校验都能通过,Real Server 就可以进行处理。所以 LVS-NAT 工作模式下 Real Server 可以是任何操作系统,只要它支持 TCP/IP 协议即可。

3-2-2、DR 模式

LVS 的 DR 工作模式,是目前生产环境中最常用的一种工作模式,网上的资料也是最多的,有的文章对 DR 工作模式的讲解还是比较透彻的:

LVS-DR 模式的优点在于:

  • 解决了 LVS-NAT 工作模式中的转发瓶颈问题,能够支撑规模更大的负载均衡场景。

  • 比较耗费网外 IP 资源,机房的外网 IP 资源都是有限的,如果在正式生产环境中确实存在这个问题,可以采用 LVS-NAT 和 LVS-DR 混合使用的方式来缓解。

LVS-DR 当然也有缺点:

  • 配置工作较 LVS-NAT 方式稍微麻烦一点,您至少需要了解 LVS-DR 模式的基本工作方式才能更好的指导自己进行 LVS-DR 模式的配置和运行过程中问题的解决。

  • 由于 LVS-DR 模式的报文改写规则,导致 LVS 节点和 Real Server 节点必须在一个网段,因为二层交换是没法跨子网的。但是这个问题针对大多数系统架构方案来说,实际上并没有本质限制。

3-2-3、TUN 模式

LVS-DR 模式和 LVS-TUN 模式的工作原理完全不一样,工作场景完全不一样。DR 基于数据报文重写,TUN 模式基于 IP 隧道,后者是对数据报文的重新封装:

IPIP 隧道。将一个完整的 IP 报文封装成另一个新的 IP 报文的数据部分,并通过路由器传送到指定的地点。在这个过程中路由器并不在意被封装的原始协议的内容。到达目的地点后,由目的地方依靠自己的计算能力和对 IPIP 隧道协议的支持,打开封装协议,取得原始协议:

可以说 LVS-TUN 方式基本上具有 LVS-DR 的优点。在此基础上又支持跨子网间穿透。

3-3、CDN 技术

CDN 技术 Content Delivery Network:内容分发网络。为什么有时我们访问互联网上的视频资源、图片资源会比较慢,甚至访问失败。其中有一个重要的原因,是资源的物理位置离客户端太远了,可能其中有 4 层 NAT 设备(相当于使用网通的线路访问电信服务器上的资源)。

我们试想一下,如果将我们要访问的资源放到离我们客户端最近的一个服务上(例如在广州的客户端访问的资源就在广州的机房)。那么是不是就解决了这个问题(这个点称为 “边缘节点”)。这就是 CDN 网络解决的问题,如下图所示:

目前 CDN 服务不需要我们进行开发,市面上有很多公司都提供免费的 / 付费的 CDN 服务(请直接在 google 或者百度上面输入:CDN,就会有很多 “推广” 信息了,在我的博文中不打广告 _)。当然如果您想自行搭建 CDN 网络,可以参考以下技术方案:

Squid:Squid 是一个缓存 internet 数据的一个软件,它接收用户的下载申请,并自动处理所下载的数据。目前,国内很多 CDN 服务商的网络都是基于 Squid 搭建的

利用 Nginx 的 proxy_cache 搭建:Nginx 中的 rewrite 技术实际上就可以实现 URL 请求重写,实现请求转发。而 Nginx 中的 proxy_cache 组件可以使得从远端请求的源数据保存在本地,从而实现一个 CDN 网络的搭建。

自己写:CDN 网络没有特别复杂的技术门槛,如果您有特别的需求,可以自己写一个。当然上图中所介绍的 CDN 网络属于第一代 CDN 网络,将第二代 / 第三代 P2P 技术加入到 CDN 原理中,可以形成第二代 CDN 网络:如下图所示:

第三代 P2P 技术又被称为混合型 P2P 技术主要是为了解决元数据服务器的处理压力,加速资源的本地化速度。关于 P2P 技术我会在讲完 “业务系统设计”、“业务通信系统设计” 后,专门做一个新的专题进行介绍。另外提一下,YouTube 的 P2P 网络就是自己做的。

4、后文介绍

要总结的内容实在太多了,我决定再开一篇文章《架构设计:负载均衡层设计方案(9)——负载均衡层总结下篇》,继续进行负载均衡层技术的总结。我们将总结 Keepalived、DNS 技术、硬件负载,并且向大家介绍更广义的负载均衡技术。