当前位置: 首页 > 玩乐 > 正文

负载均衡 当执行分发策略时

作者:admin 发布时间:2023-11-27 11:25:29 分类:玩乐 浏览:130


大家好,我是TT。

我们都知道在分布式系统中业务流程的执行会涉及到多个服务实例之间的协同工作,那么为了提高系统的整体效率和吞吐量,我们就必须以最大程度发挥每个节点的作用,而负载均衡就是保证系统运行效率的关键技术。

这也是这章要讨论的主要话题。

那么接下来我们就先通过一个具体的案例场景来理解一下负载均衡的主要作用。

假如你要设计一个分布式服务系统,在这个系统中存在一批能够独立运行的服务,并且在部署上采用了集群模式,也就是把多个服务实例集中在了一起,对外提供一种业务功能。

这样用户的任意访问请求都可以由集群中的某一个服务实例进行响应,从而防止出现单点故障,以此实现高可用。

不过这样问题也就来了,用户的一次访问请求应该由哪个服务实例来响应最为合适呢?这个问题看上去很简单,实际上却要复杂得多,因为它涉及到服务请求的路由机制。

负载均衡就是最为常见的路由机制实现方案,能够根据请求来选择合适的服务实例,也就是可以把请求的流量转发到集群中的各个服务实例,从而达到流量分摊的效果。

而支持这个过程的技术组件就叫负载均衡器。

那么现在我们来看下负载均衡器的基本结构,你可以看到来自客户端的请求通过中间的负载均衡器被分发到了各个服务实例当中,然后根据分发策略的不同会产生不同的分发结果。

这里你可以先停下来考虑一个基础性的问题,负载均衡器想要实现请求分布的前提是什么?很显然,那就是负载均衡器需要掌握各个服务实例的运行状态,也就是说它需要持有当前服务实例列表信息。

那么当负载均衡器拥有了当前服务实例列表信息后具体会怎么分发呢?首先要明确的是请求由谁来分布,针对这个问题,我们根据服务实例地址列表所存在的位置不同可以把负载均衡器分为两大类:

一类是服务器端负载均衡器;

一类是客户端负载均衡器;

我们先来看看服务端负载均衡的结构,可以看到客户端与与服务实例集群之间存在一个独立的负载均衡服务器,这台负载均衡服务器就负责将接收到的各个请求转发到运行中的某个服务实例上,提供服务器端负载均衡的工具有很多,比如常见的Apache、Nginx、HAProxy等,都实现了基于HTTP协议或TCP协议的负载均衡模块,基于服务器端的负载均衡机制的实现也比较简单,只需要在客户端与各个服务实例之间假设集中式的负载均衡器即可。

此外,负载均衡器与各个服务实例之间还需要实现服务诊断及其状态监控。

通过动态获取各个服务实例的运行时信息来决定负载均衡器的目标服务。

如果负载均衡检测到某个服务实例不可用,就会自动移除该服务实例。

这么一分析我们就能知道服务器端的负载均衡器是运行在一台独立的服务器上,它会充当代理的作用,所有的请求都需要通过负载均衡器的转发才能实现服务调用,这是它的特点。

但也是一个问题。

因为当服务器请求量越来越大时,服务器端负载均衡器就会成为系统的瓶颈,同时,一旦负载均衡器自身出现异常整个服务调用的过程都会失败。

因此在分布式架构中,为了避免服务器端这种集中式的负载均衡所带来的这种问题,我们可以采用客户端负载均衡的请求分发模式,和服务器端负载均衡器部署在服务集群前端的形式不同,在客户端负载均衡器中服务实例信息是保存在各个客户端的内部,这时候,目标服务实例地址是由客户端自身通过一定的调度算法来决定的,相比服务端负载均衡客户端负载均衡机制的主要优势就是不会出现集中式负载均衡所产生的瓶颈问题。

因为每个客户端都有自己的负载均衡器,即使单个负载均衡器失效,也不会造成严重的后果,不过客户端负载均衡也同样存在一个缺陷。

就是由于所有服务实例运行时信息都需要在各个,负载均衡器之间进行传递,因此会在一定程度上加重网络流量的负载。

好了,现在应该清楚“请求由谁来分发”这个问题了。

这个核心问题实际上也引起了一个新的概念,就是用于执行负载均衡的调度算法。

这也是我们要讨论的第二个问题,“请求分发到哪里”。

要知道无论是使用服务器端负载均衡还是客户端负载均衡,运行时的分发策略都决定了负载均衡的最终效果。

分发策略在软件负载均衡中的实现形式是一组调度算法。

我们俗称为“负载均衡算法”。

负载均衡算法有动态和静态之分,它们之间的区别就在于是否依赖于当前服务的运行状态,这些状态信息包括服务过去一段时间内的评论调用时延和所承受的连接数等。

我们先来看静态负载均衡算法,这类算法中具有代表性的是各种随机(Random)算法和轮询(Round Robin)算法。

所谓的随机算法就是在集群中随机中选择一个服务实例,它的特点是负载均衡的结果相对比较评论,随机算法的实现也比较简单,我们使用JDK自带的Rondom工具类就可以来指定服务实际的地址。

举个例子,这是来自客户端的9个请求,分别被分发到了服务A集群中的3个服务实例当中,它们的分发策略就是随机选择的而不是一个固定的规则,你可能也会用到随机算法的升级版,加权随机(weight Rondom)算法,在集群中可能存在部分性能较优的服务器,为了使这些服务器响应更多的请求,就可以通过加权随机算法提升这些服务器的权重。

如这张图实际2的权重设置的最大,所以对应的处理请求数可能也就最多,讲完随机算法我们再来看看轮询算法。

所谓轮询就是按一定顺序循环遍历整个服务实例列表,并在循环过程中为请求某指定某一个服务实例,如果循环过程到达上限,那就就从零开始继续顺序循环,直到找到下一个服务实例。

举个例子,可以看到在一个示意图中第一个请求被分发到了实际1,第二个请求被分发到了实际2,第3个请求被分发到了实际3,然后第4个请求再次被分发到了实例1,以此类推,当然,轮询的时候每个服务实例也可以具有特定的权重构成加权轮询算法。

事实上所有设计到权重的静态算法都可以转变为动态算法,因为权重可以在运行过程中动态地更新。

比如在动态轮询算法中权重值会基于各个服务器的监控并不断更新。

另外,基于服务器的实时性能分布请求也是常见的动态策略。

典型的动态算法包括最少连接数算法,最少连接数Least Connection算法是指根据集群中各个服务的当前打开连接数来确定目标服务实例。

连接数最少得服务实例会优先响应请求,当执行分发策略时,系统会根据在某一个特定的时间点下服务实例的最新连接数来判断是否执行客户端请求。

而在下一个时间点时服务实例的连接数一般都会发生相应的变化,对应的请求处理也会做相应的调整。

与最少连接数类似,服务调用时延Service Invoke Delay算法是根据服务实例的调用时延来决定负载均衡的结果。

服务器也可以根据服务调用和评论时延差值动态来调整权重。

另外在现实中有时候我们也会使用源地址哈希Source IP Hash算法,这个算法的具体实现是请求IP粘滞Sticky连接,以此尽可能地让来自同一个IP的地址访问到同一个实例。

这是一种有状态的机制,因此我们也可以把它归为动态负载均衡算法。

在Spring Cloud中实现的核心负载均衡算法包括随机、轮询、加权响应时间并发量最小优先等。

而Dubbo中则提供了随机、轮询最少活跃调用数和一致性哈希等算法。

所以可以发现,这两个框架都实现了前面介绍的一些主流算法。

但它们也根据框架自身的特点提供了一些比较有特色的策略。

当然,这两个框架也提供了开发入口供开发人员实现自定义的负载均衡算法。

以上就是这节的内容,为了更好的理解,我做了一张思维导图供大家参考。


标签:服务负载


相关推荐

最新推荐

关灯