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

文章目录

  • 微服务注册模型
  • 服务注册与发现怎么保证高可用
    • 【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 来计算哈希值,那么可以确保同一个用户的本地缓存必然在同一个节点上。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消防救援大队应用“码“上监管 实现重点领域监督全覆盖

近年以来,一直存在消防安全风险防控不精准、问题发现不及时、监督效果不明显等难点问题,我们充分利用信息化手段,探索开通“码上监督”网络举报平台,实现监督途径从“线下”拓展到“线上”,“码上监督”马上办。 问题…

容器size()无符号数导致的for循环崩溃

1.问题描述 容器size()无符号数导致的for循环崩溃 for (int index 0; index < static_cast(intVec.size())-1; index) { printf(“%d”,intVec[index]); } 如果不做强转&#xff0c;可能会有两个问题&#xff1a; &#xff08;1&#xff09;编译不过 &#xff08;2&#x…

K8S 集群搭建

1、搭建清单 2台linux服务器&#xff08;一个master节点&#xff0c;一个node节点&#xff09;&#xff0c;建议搭3台&#xff08;一个master&#xff0c;两个node&#xff09; 我使用的是腾讯云&#xff0c;节点与节点使用公网IP通信 确保2台服务器都安装了docker 2、服务…

unity 使用Vuforia扫描实体物体交互

文章目录 前言一、Vuforia是什么&#xff1f;二、Unity导入Vuforia1.去Unity - Windows – Asset Store&#xff0c;搜vuforia engine&#xff0c;添加到我的资源2.从 Unity 的菜单 Assets -> Import package -> Custom Package 导入脚本&#xff0c;添加 Vuforia Engine…

Echarts 图表添加横向 竖向滚动条

1.横向滚动条 dataZoom: [{// 设置滚动条的隐藏与显示show: true,// 设置滚动条类型type: "slider",// 设置背景颜色backgroundColor: "rgb(19, 63, 100)",// 设置选中范围的填充颜色fillerColor: "rgb(16, 171, 198)",// 设置边框颜色borderCo…

PGVector 管理工具 pgAdmin

PGVector 管理工具 pgAdmin pgAdmin 下载地址pgAdmin 安装pgAdmin 使用 pgAdmin 下载地址 https://www.postgresql.org/ftp/pgadmin/pgadmin4/ pgAdmin 安装 双击 pgadmin4-*-x64.exe 安装文件&#xff0c;选择安装路径&#xff0c;后面安装提示单击 next 就可以了。 pgAdm…

数据迁移教程 | 从 Postgre/Greenplum 到 DolphinDB

PostgreSQL 是一种开源的关系型数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;是最广泛使用的开源数据库之一。它允许用户通过添加自定义函数、数据类型和索引等方式扩展其功能&#xff0c;支持 ACID 事务&#xff0c;并使用多版本并发控制 (MVCC&#xff09;来管理并…

JDK 环境变量设置

目录 一. 前言 二. 下载 JDK 2.1. JDK 8 2.2. JDK 17 2.3. JDK 21 三. 环境变量设置 3.1. Windows 环境配置 3.1.1. 打开环境变量配置窗口 3.1.2. 配置环境变量 JAVA_HOME 3.1.3. 配置环境变量 CLASSPATH 3.1.4. 环境变量 Path 末尾追加 3.1.5. 检查JDK是否安装成…

北斗卫星推动我国法治建设

北斗卫星推动我国法治建设发展 10月26日下午&#xff0c;第二届北斗规模应用国际峰会北斗规模应用法治保障专题论坛在湖南省株洲市召开。与会专家围绕北斗法治建设全局、北斗涉外法治建设、北斗品牌塑造、北斗产业生态建设及政策法规完善等方面&#xff0c;进行了深入研讨交流。…

搬砖日记:post传数组(三种格式)

1. json型 request({url: /msg/message/batch/read,data,method: post,content-Type: application/json })2. formData数组型 Content-Type: application/x-www-form-urlencoded request({url: /msg/message/batch/read,data,method: post,})3.formData字段重复传型 把data换成…

经典文献阅读之--Fast and Robust Ground Surface Estimation...(均匀B样条采样快速估计地平面)

0. 简介 对于激光雷达的地面估计分割&#xff0c;目前其实有很多方法做了快速并鲁棒的分割&#xff0c;比如说我们之前写的一篇《经典文献阅读之–FEC》一文中就给出了快速分割的方案&#xff0c;当中第一步就是需要对地面进行分割。而我们这次看的是一篇使用均匀B样条的方法来…

第2关:多表查询

任务描述 join操作符编程要求测试说明 任务描述 本关任务&#xff1a; 使用join操作符实现多表查询。 join操作符 1.笛卡尔积&#xff0c;RXS 可直接转换为SQL语句 2.等值连接&#xff0c;记作 可直接转换为SQL语句 3.自然连接&#xff0c;记作 可转换为SQL语句 4.左外连接…

Java架构核心基础知识硬核整理,赶快收藏起来吧!!!

Java架构核心基础 lecture&#xff1a;波哥 一、数据结构和算法 1.数据结构 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同…

保护您的Google账号安全:检查和加固措施

简介&#xff1a;随着我们在日常生活中越来越依赖于Google账号&#xff0c;我们的个人信息和敏感数据也变得越来越容易受到威胁。为了确保您的Google账号的安全性&#xff0c;本文将介绍一些简单但有效的方法&#xff0c;帮助您检查和加固您的Google账号。 --- 在数字时代&am…

【工具使用】卸载VS(Visual Studio)

目录 方法一&#xff1a;使用TotalUninstaller工具方法二&#xff1a;官网的卸载方法 方法一&#xff1a;使用TotalUninstaller工具 下载地址&#xff1a;https://github.com/Microsoft/VisualStudioUninstaller/releases 1.点击下载地址&#xff0c;选择TotalUninstaller进行…

CNKI上最新硕士博士论文pdf格式文件owner密码找回难度

听人说CNKI上比较早期的硕士博士论文pdf格式文件密码修改权限Owner密码是123456&#xff0c;想办法找了几个文件试了试果然如此。 但又听人说CNKI上最新硕士博士论文pdf格式文件owner密码已经不是了。虽然直接移除这种密码的工具到处都是&#xff0c;推测一下新增的owner密码及…

从道一云到畅捷通T+通过接口配置打通数据

从道一云到畅捷通T通过接口配置打通数据 接通系统&#xff1a;道一云 在道一云坚实的技术基础上&#xff0c;道一云推出全新升级的2.0产品矩阵&#xff0c;分别是低码平台、智能门户、场景应用。基于云原生底座&#xff0c;为企业提供集智能门户解决网关流量问题、企业微信端的…

深入理解 Spring Boot 内置工具类:ReflectionUtils

文章目录 1. 什么是反射&#xff1f;2. 使用 ReflectionUtils2.1 获取类的所有字段2.2 调用方法2.3 访问字段 3. 源码分析3.1 doWithFields3.2 findMethod3.3 invokeMethod 4. 拓展与分析4.1 拓展4.2 性能考虑4.3 Java 9 模块化 5. 总结 &#x1f389;欢迎来到架构设计专栏~深入…

探索数据湖和大数据在亚马逊云服务云存储服务上的威力

文章作者&#xff1a;Libai 引言 在当今数字化的环境中&#xff0c;组织生成的数据量正以前所未有的速度增长。数据量的激增催生了对高效存储和管理解决方案的需求。数据湖和亚马逊云服务云存储服务上的大数据是一个强大的组合&#xff0c;使组织能够充分发挥其数据的潜力。 亚…

Socket网络编程(服务端和客户端代码示例)

本文主要讲解Socket网络编程。 首先介绍socket&#xff0c;包括TCP和UDP通信过程&#xff1b;然后介绍常用的函数&#xff1b;最后编写client-server例子&#xff0c;并进行测试。 文章目录 Socket介绍TCP通信过程服务器端通信过程&#xff1a;客户端通信过程&#xff1a; UDP通…