微服务的注册发现和微服务架构下的负载均衡

news2024/12/26 11:24:03

文章目录

  • 微服务注册模型
  • 服务注册与发现怎么保证高可用
    • 【1. 服务端崩溃检测】
    • 【2. 客户端容错】
    • 【3. 注册中心选型】
  • 微服务架构下的负载均衡
    • 【1.轮询与加权轮询】
    • 【2.随机与加权随机】
    • 【3.哈希与一致性哈希】
    • 【4.最少连接数】
    • 【5.最少活跃数】
    • 【6.最快响应时间】
    • 【总结】
  • 负载均衡实际应用
    • 权重
    • 本地缓存的哈希一致性问题

微服务注册模型

为什么需要服务注册与发现?一般来说,服务集群会部署在不同的机房和不同的机器上,监听不同的端口。当客户端收给服务端发送请求,怎么知道应该发送给哪个机器?这就需要用到“注册中心”。
在这里插入图片描述

针对服务注册与发现,可以分为下面几个步骤(服务上线):

    1. 服务端启动的时候,需要往注册中心里注册自身的信息,主要是定位信息。
    1. 注册成功之后,注册中心和服务端要保持心跳。
    1. 客户端第一次发起对某个服务的调用之前,要先找注册中心获得所有可用服务节点列表,随后客户端会在本地缓存每个服务对应的可用节点列表。
    1. 客户端和注册中心要保持心跳和数据同步,后续服务端有任何变动,注册中心都会通知客户端,客户端会更新本地的可用节点列表。
    1. 客户端发送请求。
    1. 服务端返回响应。
      在这里插入图片描述
      上面的这个步骤你可以看作是一个“正向”的步骤,而对应的反向步骤则是指服务端下线的过程。服务端下线的过程如下:
    1. 服务端通知注册中心自己准备下线了。
    1. 注册中心通知客户端某个服务端下线了。
    1. 客户端收到通知之后,新来的请求就不会再给该服务端发过去。
    1. 服务端等待一段时间之后,暂停服务并下线。

需要注意的是,服务端必须要等待一段时间才能下线。因为从它通知注册中心自己要下线,到客户端收到通知,是有一段延时的,这段延时就是服务端要等待的最小时间。

在这里插入图片描述

服务注册与发现怎么保证高可用

【1. 服务端崩溃检测】

在正常情况下,服务端下线都需要通知注册中心。那么万一服务端宕机了呢?在这种情况下,服务端是没办法通知注册中心的,注册中心自然也就不会通知客户端。那么客户端就会继续把请求发送给服务端,而这些请求显然都会失败。因此,为了提高可用性,需要让注册中心尽快发现服务端已经崩溃了,而后通知客户端。所以问题的关键就在于 注册中心怎么判断服务端已经崩溃了。

简单地说, 如果注册中心和服务端之间的心跳断了,就认为服务端已经崩溃了。但是,需要考虑一个特殊情况,如果注册中心和服务端之间的网络出现偶发性的抖动,那么心跳也会失败。此时服务端并没有崩溃。

影响到可用性的关键点就是注册中心需要尽快发现服务端宕机。如果服务端突然宕机,那么服务端是来不及通知注册中心的。所以注册中心需要有一种检测机制来判断服务端有没有崩溃。在服务端崩溃的情况下,要及时通知客户端,不然客户端就会继续把请求发送到已经崩溃的节点上,这种检机制就是心跳。当注册中心发现和服务端的心跳失败了,那么它就应该认为服务端可能已经崩溃了,就立刻通知客户端停止使用该服务端;但是这种失败可能是偶发性的失败,比如说因为网络偶尔不稳定造成的。所以注册中心要继续保持心跳。如果几次心跳都失败了,那么就可以认为服务端已经彻底不可用了。但是如果心跳再次恢复了,那么注册中心就要再次告诉客户端这个服务端是可用的。

如果心跳失败了要不要继续重试,是立刻重试还是间隔重试,重试的话试几次? 一般来说,在心跳失败之后如果不进行重试就直接判定服务端崩溃,那么就难以处理偶发性网络不通的问题。而如果要重试,比如重试三次,而且重试间隔是十秒钟,那么注册中心确定服务端崩溃就需要三十秒。在这三十秒内,客户端估计有成千上万的请求尝试发到崩溃的服务端,结果都失败了。

如果不考虑重试间隔的话,就难以避开偶发性的失败。比如说注册中心和服务端之间网络抖动,那么第一次心跳失败之后,你立刻重试多半也是失败的,因为此时网络很可能还是不稳定。所以比较好的策略是立刻重试几次,如果都失败了就再间隔一段时间继续重试。所有的重试机制实际上也是要谨慎考虑重试次数和重试间隔的,确保在业务可以接受的范围内重试成功。不过再怎么样,从服务端崩溃到客户端知道,中间总是存在一个时间误差的,这时候就需要客户端来做容错了。

【2. 客户端容错】

从服务端崩溃到客户端最终知道是有一段延时的。在这段延时内,客户端还是会把请求发送到已经崩溃的服务端节点上。在服务端节点崩溃之后,到注册中心发现,再到客户端收到通知,是存在一段延时的,在这段延时内,客户端发送请求给这个服务端节点都会失败。这个时候需要客户端来做一些容错。

延时怎么计算:最坏的情况下,延时等于 服务端和注册中心心跳间隔 加上 注册中心通知客户端的时间。大多数时候,注册中心通知客户端都是很快的,在毫秒级以内。因此可以认为服务端和注册中心的心跳间隔就是这个延时

一般的策略是客户端在发现调不通之后,应该尝试换另外一个节点进行重试。如果客户端上的服务发现组件或者负载均衡器能够根据调用结果来做一些容错的话,那么它们应该要尝试将这个节点挪出可用节点列表,在短时间内不要再使用这个节点了。后面再考虑将这个节点挪回去。
在这里插入图片描述

【3. 注册中心选型】

选 CP 还是选 AP 的问题。C:Consistency,数据一致性;A:Availability,服务可用性;P:Partition-tolerance,分区容错性。
一个分布式系统不可能同时满足数据一致性、服务可用性和分区容错性这三个基本需求,最多只能同时满足其中的两个。选择 CP 就是选了一致性和分区容错性,而选择 AP 就相当于选了可用性和分区容错性。(参考: 微服务的使用场景和架构设计方案 )
在这里插入图片描述

P 分区容错性是肯定要选的,那么剩下的就是选 C(一致性) 还是选 A(可用性) 了。在注册中心选型里面,一致性和可用性相比,可用性更加重要,所以应该选 AP。在选择 AP 的情况下,客户端就可能拿到错误的可用节点列表。如果客户端将请求发到错误的可用节点上,就会出现错误,此时客户端自然可以执行容错,换一个可用节点重试。

Eureka 和 Nacos 都是使用的 AP 模式; ZooKeeper使用的是CP模式,适合体量小、集群规模不大的业务场景。

微服务架构下的负载均衡

负载均衡其实就是要解决一个问题: 我该把请求发给哪个服务端?

其中一类算法是 静态负载均衡算法,例如:轮询和加权轮询、随机和加权随机,哈希和一致性哈希这些负载均衡算法。这些算法适用于请求都差不多、请求数量也足够多的情况,它们能够挑选出比较合适的节点。
还有一类算法,是 动态负载均衡算法,或者说是实时检测负载均衡算法。这一类算法依赖于实时判断所有候选节点的状态,并且从里面挑选出最合适的节点。这一类算法包含最少连接数、最少活跃请求数、最快响应时间等算法。

【1.轮询与加权轮询】

轮训算法 就是所有的候选节点轮流作为负载均衡的目标节点。
在这里插入图片描述

但是每个节点的实际处理能力可能并不一样,于是就有了一个加权的版本,就是加权轮询,此时就不再是节点轮流,而是 根据权重来轮流。比如一个节点的权重是另外一个节点的两倍,那么最终这个节点被选中的次数也会是另外一个节点的两倍。
在这里插入图片描述

图中节点1的权重是其他两个节点的三倍,所以相应地被选中的机会也是三倍。

【2.随机与加权随机】

随机就是随便挑选一个节点作为目标节点,加权随机 则是利用不同的权重来设置选中的概率。权重越大,那么被选中的机会也就越大。
在这里插入图片描述

【3.哈希与一致性哈希】

哈希算法就是选取请求里面某几个参数来计算一个哈希值,然后除以节点数量取余。这个过程几乎和随机一样,区别就在于随机算法里面用的是随机数,这里用的是根据参数计算出来的哈希值。哈希算法的选取会严重影响负载均衡的效果。假如说你计算哈希值的算法不太好,就容易导致某几个节点上负载特别高,而其他节点的负载就比较低。所以要尽可能保证哈希值计算出来的结果是均匀的。
在这里插入图片描述
一致性哈希负载均衡引入了一个哈希环的概念,服务端节点会落在环的某些位置上。客户端根据请求参数,计算一个哈希值,这个哈希值会落在哈希环的某个位置。从这个位置出发,顺时针查找,遇到的第一个服务端节点就是目标节点。

注意,在一致性哈希负载均衡算法里面,并不要求服务端节点是均匀分散在哈希环上的。(实际上,我们是希望所有的节点负载是均衡的,但是不同节点之间的间隔可以是不均匀的。)
在这里插入图片描述

【4.最少连接数】

最少连接数基于一个基本假设:如果一个服务端节点上的连接数越多,那么这个节点的负载就越高。因此在做负载均衡的时候就是看一下客户端和各个节点的连接数量,从中挑选出连接数数量最少的节点。最少连接数算法的缺陷在于,连接数并不能代表节点的实际负载,尤其是在连接多路复用的情况下。
在这里插入图片描述
比如这张示意图里,理论上来说新来的请求就会落到服务端节点 1 上,而后连接数变成 11。实际上在连接复用的情况下,客户端可能连续发 10 个请求到服务端节点 1 上,才会创建一个新连接。那么在这种情况下,服务端节点 1 的负载会比其他两个节点高很多。

【5.最少活跃数】

最少活跃数算法是用 当前活跃请求数 来代表服务端节点的负载。所谓的活跃请求,就是已经接收但是还没有返回的请求。客户端会维持一个自己发过去但是还没返回的请求数量,然后每次挑选活跃请求最少的那个服务端节点。
在这里插入图片描述
和上面“最少连接数”类似,活跃请求数量也不能真正代表服务端节点的负载。比如图中服务端节点1虽然只有10个请求,但是万一这10个请求都是较复杂的请求(例如大商家、大买家或者千万粉丝UP主的请求),那么服务端节点1的负载也会显著高于其他两个节点。

【6.最快响应时间】

最快响应时间算法用的是响应时间来代表服务端节点的负载。最快响应时间算法就是客户端维持每个节点的响应时间,而后每次挑选响应时间最短的。响应时间和前面的两个指标比起来,是一种综合性的指标,所以用响应时间来代表服务端节点负载要更加准确。但是在实现上,要注意响应时间的时效性。一般来说统计响应时间时应该只用近期请求的响应时间,并且越近的响应时间,权重应该越高。换句话说,就是采集的响应时间效用应该随着时间衰减。
在这里插入图片描述

【总结】

最少连接数、最少活跃请求数和最快响应时间,都可以看作是选择了单一的指标来代表一个节点的负载,在实际工作中可以利用这个思路来设计自己的负载均衡算法。比如说在 CPU 密集型的应用里面可以设计一个负载均衡算法,每次筛选 CPU 负载最低的节点,但是难点是需要考虑 怎么采集到所有服务端节点的 CPU 负载数据

这三个算法还有一个问题,就是它们都是客户端来采集数据的。 不同的客户端就可能采集到不同的数据,如下图所示,因为客户端 1 本身并不知道客户端 2 上还有 30 个连接,因此它选择了服务端节点 1。而实际上它应该选择服务端节点 2。
在这里插入图片描述
那怎么解决这两个问题呢?答案是让服务端上报指标,而不是客户端采集。思路是服务端在返回响应的时候顺便把服务端上的一些信息一并返回。这种思路需要微服务框架支持从服务端往客户端回传链路元数据。
在这里插入图片描述

负载均衡实际应用

在实际项目中,还可以尝试根据业务设计一个独一无二的负载均衡算法,即便使用的是最简单的轮询之类的算法,也不用担心。因为目前大规模应用的就是这种简单的算法,那些花里胡哨的算法实际上落地的并不多。

所有负载均衡算法都需要考虑请求本身
【问题】某公司用的是轮询来作为负载均衡,不过因为轮询没有实际查询服务端节点的负载,所以难免会出现偶发性的负载不均衡的问题。比如说之前发现线上的响应时间总体来说是非常均匀的,但是每隔一段时间就会出现响应时间特别慢的情况。而且时间间隔是不固定的,慢的程度也不一样。后来经过排查之后,发现是因为当一个大请求落到一个节点的时候,它会占据大量的内存和 CPU。如果这时候再有请求打到同一个节点上,这部分请求的响应时间就会非常慢。
【解决方案分析】
(业务拆分角度)这个大请求其实是一个大的批量请求,可以改为限制一批最多只能取100个,然后分为多批处理。
(隔离角度)可以稍微改一下负载均衡算法,不再是单纯的轮询了,改为每天计算一批大客户,这部分大客户的请求会在负载均衡里面被打到专门的几个节点上。虽然大客户的请求依旧很慢,但是至少别的客户不会再受到他们的影响了。

权重

需要注意,加权类的算法都要考虑权重的设置和调整,实际上在工作中可以考虑根据调用结果来动态调整权重。那么应该怎么设置权重或者怎么调整权重呢?思路如下:

  • 权重代表节点的处理能力,当然在一些场景下它也代表节点的可用性或者重要性,所以权重根据节点的实际情况来设置值就可以。权重的要点在于体现不同节点的差异性,它的绝对值并不重要。
  • 一般来说,为了进一步提高可用性,加权类的负载均衡算法都会考虑根据调用结果来动态调整权重。如果调用成功了,那么就增加权重;如果调用失败了,那么就减少权重。
  • 这里调用成功与否是一种非业务相关的概念,也就是说即便拿到了一个失败的响应,但是本身也算是调用成功了。调用失败了大多数时候是指网络错误、超时等。而在实际落地的时候,也可以考虑如果是网络引起的失败,那么权重下调就多一点,因为这一类的错误意味着问题更加严重。如果是超时这种,那么权重就下调少一点,因为这种错误是比较容易恢复过来的。
    在这里插入图片描述
    权重的调整要设置好上限和下限。比如说一般下限不能为0,因为一个节点的权重为 0 的话,它可能永远也不会被选中,又或者和 0 的数学运算会出现问题导致负载均衡失败。上限一般不超过初始权重的几倍,比如说两倍或者三倍,防止该节点一直被连续选中。

本地缓存的哈希一致性问题

在性能非常苛刻的时候,我们会考虑使用本地缓存。但是使用本地缓存可能会出现很严重的数据一致性问题,比如同一个 key 对应的请求,可能会被打到不同的节点上。这就会造成两个问题,一是缓存未命中;二是不同节点都要缓存同样的数据,导致内存浪费和数据一致性问题。

在这里插入图片描述
在这种情况下,可以把类似的请求都让同一个节点来处理,比如对相同用户数据的请求都打到同一个节点上,也就是可以使用哈希或者一致性哈希。如果考虑到节点可能上线、下线的情况,那么一致性哈希负载均衡就是最优选择。可以尝试将一致性哈希负载均衡算法和本地缓存结合在一起,以提高缓存命中率,并且降低本地缓存的总体内存消耗。
在这里插入图片描述

比如说针对用户的本地缓存,可以使用用户 ID 来计算哈希值,那么可以确保同一个用户的本地缓存必然在同一个节点上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1207117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

周报5_YMK

周报5 论文:FLASHDECODING: FASTER LARGE LANGUAGE MODEL INFERENCE ON GPUS https://arxiv.org/pdf/2311.01282.pdf 在斯坦福大学团队的 Tri Dao 等人提出了 FlashAttention 和 FlashDecoding 后,相关的工作又被很快提出,上周来自无问芯穹…

房地产信息展示服务预约小程序的作用是什么

市场中房产品牌很多,中介也比较多,各个品牌在城市中竞争激烈,然而随着线下流量匮乏及多种难题,传统商家线下经营方式变的很低效,急需通过线上实现增长。 房产不同于其它产品,转化时间较长,但又…

RedCap推动5G规模应用,紫光展锐赋能产业高质量发展

5G R17 RedCap作为面向中高速物联网场景的关键技术和解决方案,可以大幅降低终端的复杂度、成本和功耗。在当前国内5G应用规模化发展关键时期,5G R17 RedCap拥有广大的市场潜力与广泛的应用场景,将有助于推动5G规模应用、构建融通发展的5G生态…

快手自动引流软件的运行分享,以及涉及到技术与核心代码分享

先来看实操成果,↑↑需要的同学可看我名字↖↖↖↖↖,或评论888无偿分享 一、引言 引流是任何网络创业者或营销人员必备的技能之一。手动引流不仅耗时,而且效果难以保证。因此,自动引流软件应运而生,成为许多人的得力助…

多区域LCC-HVDC一次调频二次调频

多区域LCC-HVDC高压直流互联一次二次调频,后续可加入双馈永磁风机调频,储能调频等。多个四机两区域模型互联。 目前实现的主要是区域之间的调频。

掌握这11点外贸知识,能够给你外贸工作带来很大提升!

01.产品展示 关于产品展示,非常重要也一再提及,一个好的产品必须包括以下几部分: ● 产品标题准确概括产品; ● 产品图片清晰且包括细节图; ● 提供详尽的产品描述,比如型号、尺寸、材质、配件等等。最好…

【Android】统一系统动画

需求:除panel动画效果为弹出之外,其余的应用效果为渐入渐出 从系统层面统一把控动画效果,而不是单个应用自己处理 Android系统版本:9.0 代码地址 \frameworks\base\core\res\res\values\styles.xml 当时看注释,以为…

目标检测算法 - YOLOv2

文章目录 1. Batch Normalization2. High Resolution Classifier3. Anchor、Dimension Cluster、Direct location prediction4. Loss Function5. Fine-Grained Features6. Multi-Scale Training7. Faster8. Stronger Better,Faster,Stronger。 2017年&am…

使用 request 和 cheerio 库来发送 HTTP 请求

首先,我们需要导入所需的库。在这个例子中,我们将使用 request 和 cheerio 库来发送 HTTP 请求和解析 HTML。 import request from request; import cheerio from cheerio;然后,我们需要定义一个函数来发送请求并解析响应。 function getHt…

『MySQL快速上手』-⑧-内置函数

文章目录 1.日期函数1.1 获得年月日1.2 获得时分秒1.3 获得时间戳1.4 在日期的基础上加日期1.5 在日期的基础上减去时间1.6 计算两个日期之间相差多少天案例1案例22.字符串函数案例3.数学函数4.其他函数1.日期函数 1.1 获得年月日

【极客时间-系列教程】Vim 实用技巧必知必会-基本概念和基础命令:应对简单的编辑任务

vim很强大,但它的入门确实是比较高,对于初学者来说,怎么退出都是一件很难的事情, 不管你有没有遇到过,反正我是遇到过退出比较难的问题 首先介绍几个常用的命令和按键 :q! 退出不保存:w 写入不退出:r 读文件:wq 写入…

The 8th China Open Source Conference Successfully Concludes

由开源社主办的第八届中国开源年会(COSCon23)于 2023年10月29日在成都圆满收官。本次大会,为期两天,线下参会报名逾千人次,在线直播观看人数总计 168610 人,直播观看次数达 248725 次,官网累计浏…

屏幕录制为什么没有声音?让我来告诉你答案

在日常生活和工作中,屏幕录制是一项非常有用的技能,无论是为了记录教程、演示软件,还是分享游戏经验。然而,有时您可能会遇到一个常见的问题,录制的视频没有声音。本文将深入解析屏幕录制为什么没有声音,并…

合众汽车选用风河Wind River Linux系统

导读合众新能源汽车股份有限公司近日选择了Wind River Linux 用于开发合众智能安全汽车平台。 合众智能安全汽车平台(Hozon Automo-tive Intelligent Security Vehicle Plat-form)是一个面向高性能服务网关及车辆控制调度的硬件与软件框架,将于2024年中开始投入量产…

JCJC错别字检测系统安装部署手册

本手册是针对 Ubuntu 服务器环境的安装使用说明。CentOS安装手册,请参考连接: JCJC错别字系统部署-腾讯云开发者社区-腾讯云 。 安装步骤: 第一步:安装 docker 离线方式在Ubuntu 18.04 上安装Docker ,参考连接&am…

TypeError: Can‘t parse ‘center‘. Sequence item with index 0 has a wrong type

报错代码 import sys sys.path.append(rD:\文档\Temp\WX-FIles\data) # sys.path.append(rD:\文档\Temp\WX-FIles\data)p11 [125, 195] p12 [200, 275] # and the corresponding two points on the second image are:p21 [120, 190] p22 [200, 280] # TODO: write your ow…

Shiro快速入门之三

一、前言 接Shiro快速入门之二,上篇侧重于介绍认证,这篇介绍一下Shiro的授权,先初始化5张表的数据。 注:创建三条权限记录,一个admin角色分配查询和添加用户权限,一个账户qingcai18036授予管理员角色。 二…

用递归解饮料换购

乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账。 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始…

phpstudy 开启目录浏览功能

(1)在该目录下: (2)选择对应网站的配置文件; (3)修改: # Options FollowSymLinks ExecCGI Options Indexes FollowSymLinks ExecCGI

python 文本纠错库pycorrector的使用(API变更,许多介绍文章已不可用)

pycorrector是一个nice的中文检测库,在最新的版本API变更,导致许多之前的介绍文章不可用。 现将新API粘贴如下。