架构设计:负载均衡层设计方案之负载均衡技术总结篇

2020-05-25 00:00:00 技术 节点 负载 介绍 负载均衡

1、概述
通过前面文章的介绍,并不能覆盖负载均衡层的所有技术,但是可以作为一个引子,告诉各位读者一个学习和使用负载均衡技术的思路。虽然后面我们将转向“业务层”和“业务通信”层的介绍,但是对负载均衡层的介绍也不会停止。在后续的时间我们将穿插进行负载均衡层的新文章的发布,包括Nginx技术的再介绍、HaProxy、LVS新的使用场景等等。
这篇文章我们对前面的知识点进行总结,并有意进行一些扩展,以便于各位读者找到新的学习思路。
2、负载均衡层的核心思想
2-1、一致性哈希与Key的选取


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

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

2-2、轮询与权


  1. 不加权轮询,就是主控节点(任务来源点)在不考虑目标节点的任何因素的情况下(例如CPU性能、磁盘性能、网络性能),按照目标节点的列表顺序将任务依次分配下去。这是简单的轮询,也是对主控节点实现复杂性要求低的轮询。我之前的博文《架构设计:负载均衡层设计方案(2)——Nginx安装》、《架构设计:负载均衡层设计方案(4)——LVS原理》 都对这种简轮询进行了介绍:例如LVS中的“rr”参数。
  2. 加权轮询中的“权”,您可以看成是“轮询”依据的意思。“权”可以是很多种可能,可以是目标机器的性能量化值、可以是一个固定的数字(按照固定数字加权)、可以是目标节点的网络速度。例如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_* 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。
下面是一段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_modulemake && 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模式的优点在于:

  1. 配置管理简单。LVS-NAT的工作方式是LVS三种工作模式中容易理解、容易配置、容易管理的工作模式。
  2. 节省外网IP资源,一般机房分配给使用者的IP数量是有限的,特别是您购买的机架的数量不多时。LVS-NAT工作方式将您的系统架构封装在局域网中,只需要LVS有一个外网地址或外网地址映射就可以实现访问了。
  3. 系统架构相对封闭。在内网环境下我们对防火墙的设置要求不会很高,也相对容易进行物理服务器的运维。您可以设置来源于外网的请求需要进行防火墙过滤,而对内网请求开放访问。
  4. 另外改写后转给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网络解决的问题,如下图所示:


可以说LVS-TUN方式基本上具有LVS-DR的优点。在此基础上又支持跨子网间穿透。
3-3、CDN技术
CDN技术Content Delivery Network:内容分发网络。为什么有时我们访问互联网上的视频资源、图片资源会比较慢,甚至访问失败。其中有一个重要的原因,是资源的物理位置离客户端太远了,可能其中有4层NAT设备(相当于使用网通的线路访问电信服务器上的资源)。
我们试想一下,如果将我们要访问的资源放到离我们客户端近的一个服务上(例如在广州的客户端访问的资源就在广州的机房)。那么是不是就解决了这个问题(这个点称为“边缘节点”)。这就是CDN网络解决的问题,如下图所示:


目前CDN服务不需要我们进行开发,市面上有很多公司都提供免费的/付费的 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网络就是自己做的。
3、负载均衡层技术汇总
3-4、Keepalived技术
在这些文章中从来没有单独介绍Keepalived。这是因Keepalived是为了监控集群节点的工作状态,在因为某种原因不能正常提供服务的前提下,完成备机的切换。这里面有两个关键点:监控节点上提供的服务、完成网络切换。keepalived本身是不提供业务服务的,只是监控提供的服务是否正常工作,那么既然都没有可以监控的服务,那么Keepalived有什么独立使用的必要呢?
下图是Nginx + Keepalived的工作结构和LVS + Keepalived 的工作结构:


Nginx + Keepalived的工作方式


LVS + Keepalived + Nginx的工作方式
相关技术还有:
Heartbeat是Linux-HA计划中的一个重要项目,它的功能比Keepalived更强大,安装和管理也相对复杂。网络上有很多资料介绍Heartbeat和Keepalived的优缺点和使用对比。但就我自己的使用经验来说,个人更喜欢使用Keepalived,原因很简单:Keepalived安装和配置更简单,而且够用。另外Redhat Rhcs套件也可以搭建类似的HA集群,但是说实话本人没有尝试过。
3-5、DNS轮询和智能DNS
//TODO DNS技术还没有介绍
3-6、硬件负载
在这个系列的“负载均衡层设计方案”博文中,我们所提到的诸如Nginx、LVS等技术,没有详细讲述的Haproxy、Squid等技术,都是基于软件的负载技术。F5是一家公司,它的BIG-IP LTM技术是基于硬件负载的。硬件负载方案提供了软件负载技术无法提供了性能空间,并且集成了NAT映射功能、SSL加速、Cookie加密、高速缓存、攻击过滤、包过滤、动态Session保持等等很多软件负载无法提供的功能(或者需要多个软件组合使用才能提供的功能)。
但是硬件负载方案也有其缺点,主要就是建设费用比较高昂,它不像软负载可以根据系统的吞吐量的持续增加进行持续扩展。当然您可以根据系统的吞吐量需求,在前期采用软负载,后期采用硬件负载的方案。除了F5公司提供的硬件负载技术,还有Citrix公司的硬负载方案、A10公司的硬件负载方案。


4、常见负载均衡技术组合
这里我们在重新回顾一下这个系列博文中,提到的目前常用的负载均衡技术的组合方式。
4-1、独立的Nginx/Haproxy


一般的WEB系统,前段假设一个Nginx或者Haproxy服务器,基本上可以解决包括负载分发在内的很多问题了。
4-2、Nginx + Keepalived 或 Haproxy + Keepalived 或 + Heartbeat


为了保证Nginx或者HaProxy服务器的稳定性,可以使用Keepalived或者Heartbeat做一个简单的热备方案。
4-3、LVS + (Keepalived | Heartbeat) + (Nginx | Haproxy)


随着访问压力的增大,我们开始采用多层负载方案,在Nginx或者Haproxy的前段架设LVS服务,并通过Keepalived或者Heartbeat保证Keepalived的持续工作。
4-4、加如DNS轮询技术或者智能DNS路由技术


5、负载均衡技术的其他运用
在这个系列的文章中,我们全在将用于客户端使用HTTP协议请求服务器端进行处理的情况,这里的客户端可以使终用户,也可以是某个一第三方系统。但实际上负载均衡技术在信息处理领域内,不是只有这样的请求响应层才使用,在其它的技术领域也大量使用,这个小节,我们就来梳理这些技术,作为一个扩展话题。
5-1、关系型数据库系统的负载均衡
一说到关系型数据库,大家自然会联想到Oracle、MS SQL、DB2 和Mysql。在移动互联网领域,通常很多公司在走去OEI的路程。这里我们不去讨论去OEI是否是正确的,也不去讨论怎样走去OEI这条路才合理,一个不可争辩的事实是,目前很多移动互联网公司在使用Mysql数据库。
单台Mysql数据库的处理能力确实赶不上Oracle,甚至赶不上MS SQL这些商用数据库,但是我们可以为Mysql做集群来提高整个数据服务的性能。Mysql从5.1.X版本开始,就已经支持单数据节点的“表分区”功能了,但这个支持仅限于每个节点的配置,提高单个Mysql上的读写性能(还要配合底层的块存储选型,例如DAS)。而想要实现整个Mysql集群性能,就需要从更别实现读写分离了。
其中有一种成熟的Mysql集群读写分离的做法,是一台写节点做成Master节点(Master节点单机性能可以做得较高,后端可以使用DAS系统);然后多台读节点做成Salve节点,并接受来源于Master节点的同步日志(MySQL Replication技术),并通过另一个LVS进行读请求的负载,而且可以再配合单个节点上的“表分区”功能。这个做法在80%以上都是读请求的任何系统上,都可以大大增强数据库系统的整体性能,如下图所示:


从上图可以看到,来源于程序的“写”操作通过一个数据源提交给了Mysql Master,而所有的读操作则通过LVS-DR模式分发给3个Mysql Salve。这里要说明几个问题:

  1. Mysql Master和Mysql Salve的数据同步是通过MySQL Replication同步技术来实现的,这是一种基于操作日志的异步同步,虽然响应时间不能达到“毫秒”级,但是基本上还是很快很快的。如果不是银行系统、或者“秒杀系统”基本上可以满足事实性
  2. MySQL Replication会降低Mysql Master节点的20%的工作性能,但是转移了原来Mysql Master负责的所有读操作。当然,我们以后介绍“多主”方式和使用HiveDB横向切分的时候,还会重点介绍如何提高Mysql的写性能。
  3. 事实上正式的开发架构中,我们不会给程序员两个数据源,这样既不利于代码的管理,也增加了开发难度。我们会采用类似Mysql-Proxy、Amoeba之类的软件实现数据源的整个。
  4. 后面在介绍数据存储层架构的时候,我还会介绍多种成熟的可靠的Mysql集群、Mysql读写分离、Mysql横向扩展方式,和读者讨论如何实现几十台Mysql节点的运行和管理。

5-2、分布式存储系统的负载均衡
分布式存储系统目前有很多,Ceph、Swift、MFS、HDFS。他们有的是基于对象存储的,有的是基于快存储的(在《标准Web系统的架构分层》这篇博文中,我对块存储、文件存储和对象存储做了较详细的介绍,后文我们还将详细介绍存储系统)。但是他们有一个或者多个主控节点(有的叫namenode、有的叫master、有的叫Metadata),无论怎么叫,他们都有一些相同的功能:

  1. 计算“数据该存储在哪里”的问题
  2. 协调控制“数据是否正确存储”的问题
  3. 监控“数据节点”的健康状态
  4. 转移数据
  5. 回答客户端“到哪里取数据”的问题
  6. 。。。。。

在处理问题的过程中,这些控制节点实际上起到的就是负载分发的作用,他们的基本原理都是通过“一致性hash算法”,对“数据该存储在”哪里的问题进行分析(用来做hash的属性依据不同而已):


5-3、更广义的负载均衡系统
相同的客流量下,银行多个窗口排队的等待时间肯定比一个窗口排队的时间短;同样的车流量,8车道肯定比6车道的通过率高;把一个任务拆分成多个任务由多个人负责处理其中的一部分,肯定比一个人做一个大任务的时间短;
负载均衡的核心思想在于分流、关键问题在于如何分流、评价标准在于分流后的吞吐量。
关注我,私信回复“架构”获取面试宝典《Java核心知识点整理.pdf》“,覆盖了JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构等等”。

相关文章