26负载均衡怎样提升系统的横向扩展能力?
基础篇中,我们了解了高并发系统设计三个通用的方法,缓存、异步、横向扩展。目前你接触了缓存的使用,也了解了如何使用消息队列异步处理业务逻辑。那么本章我们来看下如何增强系统横向扩展能力。
实际工作中,你经常使用的负载均衡组件应该 Nginx,他的作用应该是承接前段 http请求,然后按照设计的既定策略转发到后端对应的服务上去。这样我们可以随时扩容业务服务来抵挡流量峰值。与DNS不同,Nginx可以在域名和请求URL上做更细致的流量管控,也提供更复杂的负载均衡策略。
那么在微服务架构中,如何使用负载均衡呢? 负载均衡服务器的种类
负载均衡的含义:将负载(访问的请求)均衡的分配到多个节点上,这样可以减少单个节点的请求,提高系统的性能。
同时,负载均衡作为流量的入口,可以对请求方屏蔽后端服务的细节,实现对业务方的无感知扩容。
负载均衡大致可以分为两位: 代理类的负载均衡和客户端负载均衡
代理类负载均衡以服务的方式单独部署,所有请求都要经过负载均衡服务,在负载均衡选出一个合适的服务节点后,再调用这个服务节点来实现服务的分发。
由于这类服务需要承担极高的流量,所以对于性能要求极高,代理类负载均衡有许多开源实现,比如 LVS、Nginx 等等。LVS 在 OSI 网络模型中的第四层,传输层工作,所以 LVS 又可以称为四层负载;而 Nginx 运行在 OSI 网络模型中的第七层,应用层,所以又可以称它为七层负载(你可以回顾一下02 讲的内容)。
在项目的架构中,我们一般会同时部署 LVS 和 Nginx 来做 HTTP 应用服务的负载均衡。也就是说,在入口处部署 LVS 将流量分发到多个 Nginx 服务器上,再由 Nginx 服务器分发到应用服务器上,为什么这么做呢?
主要LVS 和 Nginx 的特点决定,LVS 在网络栈的四层做请求包的转发,请求包转发之后,客户端和后端服务直接建立链接,后续的响应包不会再经过LVS服务器,所以相比 Nginx 性能会更高,也能够承担更高的并发。
可 LVS 缺陷是工作在四层,而请求的 URL 是七层的概念,不能针对 URL 做更细致的请求分发,而且 LVS 也没有提供探测后端服务是否存活的机制;而 Nginx 虽然比 LVS 的性能差很多,但也可以承担每秒几万次的请求,并且它在配置上更加灵活,还可以感知后端服务是否出现问题。
因此,LVS 适合在入口处承担大流量的请求分发,而 Nginx 要部署在业务服务器之前做更细维度的请求分发。 我给你的建议是,如果你的 QPS 在十万以内, 那么可以考虑不引入 LVS 而直接使用 Nginx 作为唯一的负载均衡服务器,这样少维护一个组件,也会减少系统的维护成本。
不过这两个负载均衡服务适用于普通的 Web 服务,对于微服务架构来说,它们是不合适的。因为微服务架构中的服务节点存储在注册中心里,使用 LVS 就很难和注册中心交互获取全量的服务节点列表。另外,一般微服务架构中,使用的是 RPC 协议而不是 HTTP 协议,所以 Nginx 也不能满足要求。
所以,我们会使用另一类的负载均衡服务,客户端负载均衡服务,也就是把负载均衡的服务内嵌在 RPC 客户端中。
它一般和客户端应用部署在一个进程中,提供多种选择节点的策略,最终为客户端应用提供一个最佳的、可用的服务端节点。这类服务一般会结合注册中心来使用,注册中心提供服务节点的完整列表,客户端拿到列表之后使用负载均衡服务的策略选取一个合适的节点,然后将请求发到这个节点上。
常见的负载均衡策略有哪些一类是静态策略,也即是说负载均衡在选择后端服务节点时,是不考虑后端服务的存活状态的。 一类动态策略,也就是说负载均衡会依照后端服务存活状态,来选择哪一个服务的转发
常见的静态策略有几种,使用最广泛的轮询策略,RoundRobin,RR,这种策略会记录上次请求的服务地址序号,下次请求过来,顺次选择下一个服务节点。 AtomicInteger lastCounter = getLastCounter();//获取上次请求的服务节点的序号 List serverList = getServerList(); // 获取服务列表 int currentIndex = lastCounter.addAndGet(); //增加序列号 if(currentIndex >= serverList.size()) { currentIndex = 0; } setLastCounter(currentIndex); return serverList.get(currentIndex);
其实是一种通用策略,大多数负载均衡服务器都支持。但是这种策略一个弊端 就是 不考虑后端服务器的配置,因为后面服务的机器配置不可能都是一致的,这样导致每台服务节点承受的能力也不同,这点是轮询没有考虑到的。
所以就出现了一种 这种策略就是带有权重的轮询策略。 以应对后端服务不同的承载能力。
除了这两种策略之外,目前开源的负载均衡服务还提供了很多静态策略:
Nginx 提供了 ip_hash 和 url_hash 算法; LVS 提供了按照请求的源地址和目的地址做 Hash 的策略; Dubbo 也提供了随机选取策略以及一致性 Hash 的策略。
而目前开源的负载均衡服务中,也会提供一些动态策略,我强调一下它们的原理。
在负载均衡服务器上会收集对后端服务的调用信息,比如从负载均衡端到后端服务的活跃连接数,或者是调用的响应时间,然后从中选择连接数最少的服务,或者响应时间最短的后端服务。 我举几个具体的例子: Dubbo 提供的 LeastAcive 策略,就是优先选择活跃连接数最少的服务; Spring Cloud 全家桶中的 Ribbon 提供了 WeightedResponseTimeRule 是使用响应时间给每个服务节点计算一个权重,然后依据这个权重,来给调用方分配服务节点。
这些策略的思考点是从调用方的角度出发,选择负载最小、资源最空闲的服务来调用,以期望能得到更高的服务调用性能,也就能最大化地使用服务器的空闲资源,请求也会响应得更迅速。所以我建议你,在实际开发中,优先考虑使用动态的策略。
到目前为止,你已经可以根据上面的分析,选择适合自己的负载均衡策略,并选择一个最优的服务节点。 那么问题来了: 你怎么保证选择出来的这个节点,一定是一个可以正常服务的节点呢?如果你采用的是轮询的策略,选择出来的是一个故障节点又要怎么办呢?所以,为了降低请求被分配到一个故障节点的几率,有些负载均衡服务器还提供了对服务节点的故障检测功能。 如何检测节点是否故障
微服务化架构中,服务节点会定期地向注册中心发送心跳包,这样注册中心就能够知晓服务节点是否故障,也就可以确认传递给负载均衡服务的节点一定是可用的。
但对于 Nginx 来说, 我们要如何保证配置的服务节点是可用的呢?
这就要感谢淘宝开源的 Nginx 模块nginx_upstream_check_module了,这个模块可以让 Nginx 定期地探测后端服务的一个指定的接口,然后根据返回的状态码来判断服务是否还存活。当探测不存活的次数达到一定阈值时,就自动将这个后端服务从负载均衡服务器中摘除。 它的配置样例如下: upstream server { server 192.168.1.1:8080; server 192.168.1.2:8080; check interval=3000 rise=2 fall=5 timeout=1000 type=http default_down=true;//检测间隔为3秒,检测超时时间是1秒,使用http协议。如果连续失败次数达到5次就认为服务不可用;如果连续成功次数达到2次,则认为服务可用。后端服务刚启动时状态是不可用的 check_http_send "GET /health_check HTTP/1.0r r "; //检测URL check_http_expect_alive http_2xx; //检测返回状态码为200时认为检测成功 }
Nginx 按照上面的方式配置之后,你的业务服务器也要实现一个"/health_check"的接口,在这个接口中返回的 HTTP 状态码,这个返回的状态码可以存储在配置中心中,这样在变更状态码时,就不需要重启服务了
节点检测的功能,还能够帮助我们实现 Web 服务的优雅关闭。在24 讲中介绍注册中心时,我曾经提到,服务的优雅关闭需要先切除流量再关闭服务,使用了注册中心之后,就可以先从注册中心中摘除节点,再重启服务,以便达到优雅关闭的目的。那么 Web 服务要如何实现优雅关闭呢?接下来,我们了解一下有了节点检测功能之后,服务是如何启动和关闭的。
在服务刚刚启动时, 可以初始化默认的 HTTP 状态码是 500,这样 Nginx 就不会很快将这个服务节点标记为可用,也就可以等待服务中依赖的资源初始化完成,避免服务初始启动时的波动。
在完全初始化之后,再将 HTTP 状态码变更为 200,Nginx 经过两次探测后,就会标记服务为可用。在服务关闭时,也应该先将 HTTP 状态码变更为 500,等待 Nginx 探测将服务标记为不可用后,前端的流量也就不会继续发往这个服务节点。在等待服务正在处理的请求全部处理完毕之后,再对服务做重启,可以避免直接重启导致正在处理的请求失败的问题。 这是启动和关闭线上 Web 服务时的标准姿势,你可以在项目中参考使用。
跑步装备之运动手环从自己知道有手环这个新奇的电子产品以来,对它的关注从来就不曾停滞。1。最早入手的是连爱手环,没有显示屏,需要下载app,遇到问题还需要和客服联系重置,相当之麻烦。2。第二个手环是荣
有神通的符大概7一8岁的时候,父亲很神秘的拿出一块木板,大小好像就象厨房的切菜板那么大,厚度大概6公分左右,正反画着不同的符,父亲说,晚上睡觉时放到枕头下,能做不同的梦,如果木板正面朝上,晚
大蒜的故事湖北素有千湖之称,渔资源丰富,人民富余,生产的大米倾销全国,其中有个小城名钟祥,钟祥有个郢中镇,郢中镇有个王家湾,王家湾有个王老汉,在家排行老三又名王幺儿,王幺儿高中毕业,继承祖业
鸿星尔克奇弹lite初体验7月31日,周六,晴。大太原的早上5点半天亮,洗漱一下出发,继续打卡玉门河公园,热热身基本到了5点50分。新鞋在脚,拔腿就跑呲牙前三公里身体感知力明显,缓震表现不错,在转弯时,奇弹
纯净水,天然水,矿泉水!你喝的哪一种?纯净水,天然水,矿泉水都是什么水?小伙伴们,你喝的是哪一种呢?喝瓶装水是当今人们生活出行运动救援等必不可少的一项内容,瓶装水的种类五花八门,不同牌子的水不仅包装不同,价格也不同,甚
溜背轿跑SUV哈弗H6S上市13。89万元起10月30日晚,哈弗SUV官方宣布,旗下的哈弗H6S车型上市,新车是一款轿跑SUV,推出了5种配置版本可选,官方指导价区间为13。89万元16。49万元。外形方面,新车的前脸采用的
动力升级奔腾B702。0T版上市13。59万元起10月29日,一汽奔腾官方宣布,旗下的奔腾B70新增2。0T版车型可选,新车推出了两种配置版本,官方指导价分别是13。59万元以及14。59万元。作为新增的车型,新车在外形方面和在
约合人民币59。6万起新款雷克萨斯LC海外售价公布悬架升级日前,雷克萨斯正式发布了新款LC500车型,新车在外形内饰方面变动不大,但对悬架进行了升级,美国市场的起售价为93050美元,约合人民币59。6万元。外形方面,新车的前脸采用的是雷
福特新款锐际就长这样?海外谍照已曝光有望配轻混系统日前,外媒曝光了一组福特新款Kuga车型的谍照,应该是中期改款车型,在国内对应的车型是锐际,未来国产版锐际中期改款也有望以此为蓝本打造。从谍照来看,新车的前脸依然采用了福特家族化的
15。66万元起2022款奇瑞新能源大蚂蚁上市配置动力都有升级10月28日,奇瑞新能源官方宣布,旗下的2022款大蚂蚁车型上市,新车推出3款车型可选,官方指导价区间为15。66万元17。99万元。作为年度改款车型,新车在外形方面变动并不大,前
思域姊妹车广汽本田型格有望11月1日亮相配卡片钥匙据国内媒体报道,广汽本田旗下的性格车型将于11月1日首发亮相,新车是东风本田十一代思域的姊妹车,也是广本首次在国内推出思域的姊妹车型。在此前的报道中,广汽本田型格预计首发亮相的时间