松花皮蛋的黑板报
  • 分享在京东工作的技术感悟,还有JAVA技术和业内最佳实践,大部分都是务实的、能看懂的、可复现的

扫一扫
关注公众号

分布式系统之负载均衡(案例篇)

博客首页文章列表 松花皮蛋me 2019-12-04 13:10

我们知道单机的承载能力和垂直扩展能力都是有上限的,它无法满足高并发高吞吐量的场景,所以常使用水平扩展也就是增加机器数量来满足需求。但是不同机房、同机房不同年代上架的机器的性能也是千差万别的,甚至业务之前申请到的都是8核16G内存的配置脱销了(申请时抢不到),我们只能放低身位选择4核8G内存的服务器,那就注定了不同的服务器所能承担的吞吐量不一样。问题就来了,一只木桶能盛多少水,并不取决于最长的那块木板,而是取决于最短的那块木板。幸运的是,前人发明了负载均衡算法,从而有效解决了这个问题。

负载均衡算法是一种将数据流量按需分配给服务器去响应的算法,通常有简单轮询、加权轮询、粘性Session(一致性哈希)、最少连接数等等算法,本文不会讲解这些算法的具体原理,而是从实践出发,接下来就和我一起往下看吧。


1、负载均衡的好处只有减少机器性能差别产生的木桶效应吗?

答案肯定是否定的。

不少运营商和公司的办公职场都会将域名解析的结果进行缓存,减少递归查询的开销,然而缓存时间我们是不可控的,当我们急需修改解析记录止损时,并不能立即生效,效果显示差强人意。有了负载均衡就不一样了,我们将域名通过A记录解析到负载均衡节点上也就是VIP(virtual IP address)节点,再由VIP节点转发到后端的实例上,当需要变更分流规则时,只需要变更分流规则的路由映射信息就能立即见效。

在京东,一个域名可以有多个不同机房的VIP节点,每个VIP节点可以挂载到不同的集群上,不同的集群(集合)可以挂载不同的服务节点。好处就是,通过基于HTTP协议的Dns解析(HttpDns)和LBS定位,可以使得廊坊机房进来的流量(出口为廊坊机房的地区运营商)可以先到廊坊机房的VIP节点上再到廊坊集群的廊坊机器实例上。可以看到,这种组合设计能轻松满足流量同机房调度的需求。

除了流量调度功能外,负载均衡通常还充当一个“网关”的作用,比如配置HTTPS协议、HTTP请求强跳到HTTPS (也就是HSTS协议)、攻击拦截、流量统计、健康检查等等。

2、负载均衡的分类有哪些?

目前负载均衡器的种类分为软件和硬件,软件类代表有Nginx、Lvs、Haproxy,而硬件最有代表性的就是F5。除了按基础设施来分类外,通常还有两种分类方法,一种是基于HTTP协议的七层负载均衡和基于TCP的四层负载均衡,另外一种是出向和入向的流量(服务请求和响应)是否均通过负载均衡器。

3、有了负载均衡,请求链路变长了,问题排查会不会更加复杂?

其实使用负载均衡实现流量调度和系统进行微服务拆分,都是为了提高服务的吞吐量,也都引入了服务冶理相关的烦恼。比如说,我们在平时的软件设计中,会定义好统一的正常响应和异常响应框架,同理,在公司层面也会定义有统一的静态错误页,比如”提示页面走丢了,请去其他活动页逛逛”。

那么问题来了,当我们看到这个错误页,如何判断是后端请求超时还是服务异常,还是说后端连通性,或者负载均衡节点出错了呢?幸运的是,由于负载均衡器职责单一,架构形态可控,这个问题并不是真的那么吓人。在京东,负载均衡器会根据错误原因重写错误页的链接,附上错误标识,提高排查问题的效率。可以看到,这是标准先行给我们带来的好处。

4、使用了负载均衡,后端真实实例负载(CPU使用率)不平均,可能是哪些原因?

我们前面说过负载均衡算法有一种叫做粘性Session的算法,它能让相同的请求来源都落到相同的机器上,即使有个别实例不再挂载,也只会影响有效的请求。它的原理是请求对象和VIP节点都进行相同Hash算法处理后映射到一个圆环中,顺时针查找请求对象映射位置的下一个节点,则是命中的节点,如果没有找到则返回圆环的第一个节点。但是它不能取代存储登录态的分布式缓存,因为此算法开销不划算。如果使用此算法,在进行测试时或者请求量级过小时都有可能导致后端实例负载不均。

另外使用基于TCP的四层负载时也有相同的症状,因为它是基于源地址保持连接的。在京东,是利用Dpdk库直接从网卡获取数据包,根据本地的Session表和VIP映射关系,修改四元组(源IP,目的IP,源端口,目的端口)后将数据包通过网卡发送出去。我们有个不成文的约定,每秒请求数超过一万的业务,都强制使用四层负载均衡。

如果不是上面的两个场景,也不是使用了Websocket协议保持长连接,仍然出现负载倾斜现象,那很有可能是(机器配置)权重问题或者各个VIP所挂载的机器数有差异。

5、负载均衡健康检查机制有哪些?

假设负载均衡设备与后端实例网络间出现故障,或者后端实例响应异常,负载均衡设备依然把一部分数据流量引向那台服务器,这势必造成大量的服务请求被丢失,达不到高可用性的要求。所以良好的负载均衡策略应有对网络故障、服务器系统故障、应用服务故障的检查方式和能力。常见的检测方式有如下三种。

第一种是Ping侦测。通过Ping的方式检测服务器及网络系统状况,此种方式简单快速,但只能大致检测出网络及服务器上的操作系统是否正常,对服务器上的应用可用性检测就无能为力了。

第二种是Telnet侦测。检测服务器上某个TCP端口(比如HTTP的80端口)是否正常来判断服务是否正常。

第三种是HTTP URL侦测。比如向HTTP服务器发出一个对main.html文件的访问请求,如果收到错误信息,则认为服务器出现故障。

在京东,负载均衡健康检查使用的是第二种,发布系统发布结果检查使用的第三种。比如,负载均衡器,每隔一段时间检查一次,如果实例有多次异常,先标记为不可用,新请求流量不会调度到该台服务器上,等待之前的请求全部响应或者超时响应后,将其标记为热备状态。

6、由于网络波动,负载均衡器会不会误以为后端实例全部都不存活,然后出现服务不可用的情况?

这个问题类似于,由于网络波动(注册中心与服务提供者间网络异常),服务注册中心检测到服务提供者所有实例都处于亚健康状态或者不存活了,是否通知服务使用者(消费者)更新服务注册节点列表,也就是告诉服务使用者(消费者)此时该服务无可用实例。比较好的做法是,服务探测由服务使用者(消费者)完成,或者通过健康检查机制注册中心只能踢掉一定比例的实例。

事实上,负载均衡检查到在线的实例状态都异常时,会尝试使用处在备份(热备)状态的实例,如果还是失败,就会返回503 service unavailable错误。同理,负载均衡节点(VIP)也有在线和热备的状态。

总体来看,负载均衡是应对海量之道不可或缺的利器。如果这篇文章有帮助到你,欢迎分享给你的朋友或者点个在看。