负载均衡:怎样提升系统的横向扩展能力?

news/2024/7/10 1:57:30 标签: 负载均衡

负载均衡:怎样提升系统的横向扩展能力?

在实际的工作中,我们经常使用的负载均衡的组件应该算是 Nginx,它的作用是承接前端的 HTTP 请求,然后将它们按照多种策略,分发给后端的多个业务服务器上。这样,我们可以随时通过扩容业务服务器的方式,来抵挡突发的流量高峰。与 DNS 不同的是, Nginx 可以在域名和请求 URL 地址的层面做更细致的流量分配,也提供更复杂的负载均衡策略。

我们可能会想到,在微服务架构中,我们也会启动多个服务节点,来承接从用户端到应用服务器的请求,自然会需要一个负载均衡服务器,作为流量的入口,实现流量的分发。那么在微服务架构中,如何使用负载均衡服务器呢?

负载均衡服务器的种类

负载均衡的含义是:将负载(访问的请求)“均衡”地分配到多个处理节点上。这样可以减少单个处理节点的请求量,提升整体系统的性能。

同时,负载均衡服务器作为流量入口,可以对请求方屏蔽服务节点的部署细节,实现对于业务方无感知的扩容。它就像交通警察,不断地疏散交通,将汽车引入合适的道路上。

而在我看来,负载均衡服务大体上可以分为两大类:一类是代理类的负载均衡服务;另一类 是客户端负载均衡服务。

代理类的负载均衡服务,以单独的服务方式部署,所有的请求都要先经过负载均衡服务,在负载均衡服务中,选出一个合适的服务节点后,再由负载均衡服务,调用这个服务节点来实现流量的分发。

在这里插入图片描述
由于这类服务需要承担全量的请求,所以对于性能的要求极高。代理类的负载均衡服务有很 多开源实现,比较著名的有 LVS,Nginx 等等。LVS 在 OSI 网络模型中的第四层,传输层 工作,所以 LVS 又可以称为四层负载;而 Nginx 运行在 OSI 网络模型中的第七层,应用层,所以又可以称它为七层负载。

在项目的架构中,我们一般会同时部署 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),这种策略会记录上次请求后端服务的地址或者序号,然后在请求时,按照服务列表的顺序,请求下一个后端服务节点。

它其实是一种通用的策略,基本上,大部分的负载均衡服务器都支持。轮询的策略可以做到 将请求尽量平均地分配到所有服务节点上,但是,它没有考虑服务节点的具体配置情况。比如,有三个服务节点,其中一个服务节点的配置是 8 核 8G,另外两个节点的配置是 4 核 4G,那么如果使用轮询的方式来平均分配请求的话,8 核 8G 的节点分到的请求数量和 4 核 4G 的一样多,就不能发挥性能上的优势了

所以,我们考虑给节点加上权重值,比如给 8 核 8G 的机器配置权重为 2,那么就会给它分 配双倍的流量,这种策略就是带有权重的轮询策略

除了这两种策略之外,目前开源的负载均衡服务还提供了很多静态策略:

  • Nginx 提供了 ip_hash 和 url_hash 算法;
  • LVS 提供了按照请求的源地址,和目的地址做 hash 的策略;
  • Dubbo 也提供了随机选取策略,以及一致性 hash 的策略;

轮询和带有权重的轮询策略,能够将请求尽量平均地分配到后端服务节点 上,也就能够做到对于负载的均衡分配,在没有更好的动态策略之前,应该优先使用这两种策略,比如 Nginx 就会优先使用轮询的策略。

而目前开源的负载均衡服务中,也会提供一些动态策略,看一下它们的原理。

负载均衡服务器上会收集对后端服务的调用信息,比如从负载均衡端到后端服务的活跃连 接数,或者是调用的响应时间,然后从中选择连接数最少的服务,或者响应时间最短的后端 服务。

如何检测节点是否故障

在微服务化架构中,服务节点会定期地向注册中心发送心跳 包,这样注册中心就能够知晓服务节点是否故障,也就可以确认传递给负载均衡服务的节 点,一定是可用的。

但对于 Nginx 来说,我们要如何保证配置的服务节点是可用的呢?

这就要感谢淘宝开源的 Nginx 模块nginx_upstream_check_module了,这个模块可以让 Nginx 定期地探测后端服务的一个指定的接口,然后根据返回的状态码,来判断服务是否还存活。当探测不存活的次数达到一定阈值时,就自动将这个后端服务从负载均衡服务器中摘除。

Nginx 按照上面的方式配置之后,你的业务服务器也要实现一个“/health_check”的接口,在这个接口中返回的 HTTP 状态码,这个返回的状态码可以存储在配置中心中,这样 在变更状态码时,就不需要重启服务了。

在服务刚刚启动时,可以初始化默认的 HTTP 状态码是 500,这样 Nginx 就不会很快将这个服务节点标记为可用,也就可以等待服务中,依赖的资源初始化完成,避免服务初始启动时的波动。

在完全初始化之后,再将 HTTP 状态码变更为 200,Nginx 经过两次探测后,就会标记服务为可用。在服务关闭时,也应该先将 HTTP 状态码变更为 500,等待 Nginx 探测将服务 标记为不可用后,前端的流量也就不会继续发往这个服务节点。在等待服务正在处理的请求 全部处理完毕之后,再对服务做重启,可以避免直接重启导致正在处理的请求失败的问题。

总结

我们了解了与负载均衡服务相关的一些知识点,以及在实际工作中的运用技巧。要记住以下几个重点:

  • 网站负载均衡服务的部署,是以 LVS 承接入口流量,在应用服务器之前,部署 Nginx 做细化的流量分发,和故障节点检测。当然,如果你的网站的并发不高,也可以考虑不引 入 LVS。
  • 负载均衡的策略可以优先选择动态策略,保证请求发送到性能最优的节点上;如果没有合适的动态策略,那么可以选择轮询的策略,让请求平均分配到所有的服务节点上。
  • Nginx 可以引入 nginx_upstream_check_module,对后端服务做定期的存活检测,后端的服务节点在重启时,也要秉承着“先切流量后重启”的原则,尽量减少节点重启对于整体系统的影响。

很多人会认为,像 Nginx、LVS 应该是运维所关心的组件,作为开发人员不用操心维护。不过通过今天的学习应该可以看到:负载均衡服务是提升系统扩展性,和性能的重要组件,在高并发系统设计中,它发挥的作用是无法替代的。理解它的原理,掌握使用它的正确姿势,应该是每一个后端开发人员的必修课。


http://www.niftyadmin.cn/n/719629.html

相关文章

存储过程使用动态游标一例

数据表结构如下:SQL> desc record; Name Type Nullable Default Comments ----------- ------------ -------- ------- -------- RECORD_GUID VARCHAR2(50) Y DNIS VARCHAR2(15) Y ANI …

多机房部署:跨地域的分布式系统如何做?

多机房部署:跨地域的分布式系统如何做?多机房部署的难点是什么?逐步迭代多机房部署方案同城双活异地多活总结多机房部署的难点是什么? 多机房部署的含义是:在不同的 IDC 机房中,部署多套服务,这…

CSS 外边距(margin)重叠及防止方法

边界重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容、补白、边框)重合在一起而形成一个单一边界。 两个或多个块级盒子的垂直相邻边界会重合。结果的边界宽度是相邻边界宽度中最大的值。如果出现负边界,则在最大的正边界中减去绝对值最…

更为完整的Hough变换线检测

RGB imread(fenkuai.bmp);%jaynes-thesis Irgb2gray(RGB); % 图片用的是灰度图像, [x,y]size(I); BWedge(I); figure;imshow(I);title(原图) figure;imshow(BW);title(边缘检测图像) rho_maxfloor(sqrt(x^2y^2))1; %由原图数组坐标算出ρ最大值,并取整数…

给系统加上眼睛:服务端监控要怎么做?

给系统加上眼睛:服务端监控要怎么做?监控指标如何选择如何采集数据指标监控数据的处理和存储总结在一个项目的生命周期里,运行维护占据着很大的比重,在重要性上,它几乎与项目研发并 驾齐驱。而在系统运维过程中&#x…

【转】线程、Thread类和线程终止

一、线程Thread启动 0. Thread类实现了java.lang.Runnable接口,即实现了run方法。虽然在Sun JDK中,start()调用了start0()方法,start0()方法又是native的,但实际上新的线程就是调用了Thread的run()方法,当然这native的…

P1909 买铅笔

题目描述 P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物。她发现商店一共有 3种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起 见,P老师决定只买同一种包装的铅笔。 商店不允许将铅笔的包装拆开&#xff0…

应用性能管理:用户的使用体验应该如何监控?

应用性能管理:用户的使用体验应该如何监控?如何搭建 APM 系统需要监控用户的哪些信息总结我们了解了服务端监控搭建的过程。有了监控报表之后,团队在维护垂直电商系统时,就可以更早地发现问题,也有直观的工具辅助我们分…