深入理解微服务中的负载均衡算法与配置策略

news2024/11/17 11:24:59

负载均衡算法

我们首先来探讨一下默认情况下Ribbon使用的负载均衡算法。有些人可能会说它使用轮询算法,因为在本地测试时,我们经常会看到轮询的效果。然而,简单地依赖这种表面的观察来回答面试题是有风险的。实际上,忽略了深入理解源代码可能会导致严重的误解。

尽管实践是增长知识的一部分,但是在真实的生产环境中,尤其是跨多个数据中心部署的情况下,我们无法简单地将问题简化为本地集群的测试环境。

获取服务器ip

我们接着上一篇内容,讨论如何选择服务器的步骤如下复述:

    public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
            throws IOException {
        ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
        Server server = getServer(loadBalancer, hint);
        if (server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        }
        RibbonServer ribbonServer = new RibbonServer(serviceId, server,
                isSecure(server, serviceId),
                serverIntrospector(serviceId).getMetadata(server));

        return execute(serviceId, ribbonServer, request);
    }

获取负载均衡器——ZoneAwareLoadBalancer

我们来看看getServer方法,突然间出现这么多负载均衡器,应该怎么处理呢?这时候最好的方法就是查看自动配置,看看哪些被注入进来了。

image

中间步骤大家就不用再找了,我已经事先找好了,就在这里:

image

这张图包含两个关键信息:首先是注入了一个IRule规则,其次是将该IRule规则应用到了ZoneAwareLoadBalancer负载均衡器中。好的,现在我们清楚了接下来的步骤。接下来我们继续查看

    public Server chooseServer(Object key) {
        if (!ENABLED.get() || getLoadBalancerStats().getAvailableZones().size() <= 1) {
            logger.debug("Zone aware logic disabled or there is only one zone");
            return super.chooseServer(key);
        }
        Server server = null;
        try {
            //省略多余代码
            Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, triggeringLoad.get(), triggeringBlackoutPercentage.get());
            logger.debug("Available zones: {}", availableZones);
            if (availableZones != null &&  availableZones.size() < zoneSnapshot.keySet().size()) {
                String zone = ZoneAvoidanceRule.randomChooseZone(zoneSnapshot, availableZones);
                logger.debug("Zone chosen: {}", zone);
                if (zone != null) {
                    BaseLoadBalancer zoneLoadBalancer = getLoadBalancer(zone);
                    server = zoneLoadBalancer.chooseServer(key);
                }
            }
        } catch (Exception e) {
            logger.error("Error choosing server using zone aware logic for load balancer={}", name, e);
        }
        //省略多余代码
    }

如果是在我们本地环境,通常会执行第一个if分支;但如果是在生产环境并配置了多个区域,那么会执行下面的分支。让我们一起来看看。

无配置区域情况

让我们来看看第一种情况,即如果没有区域或者只有一个区域,负载均衡规则是如何应用的。我们将查看父类负载均衡器BaseLoadBalancer的代码。

public class BaseLoadBalancer extends AbstractLoadBalancer implements
        PrimeConnections.PrimeConnectionListener, IClientConfigAware {   
    private final static IRule DEFAULT_RULE = new RoundRobinRule();

    protected IRule rule = DEFAULT_RULE;
    
    public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            try {
                return rule.choose(key);
            } catch (Exception e) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
                return null;
            }
        }
    }
    
     void initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping, LoadBalancerStats stats) {
        // 省略部分代码
        setRule(rule);
        // 省略部分代码
    }
}

这里可以看到是有默认的IRule规则的——RoundRobinRule,但是别冲动,因为我们Spring自动托管的IRule规则还没用上,不可能这么简单的走轮训。我们可以看到这里是有设置的地方的。我也抓出来了。

最后让我们再来看看我们的ZoneAwareLoadBalancer生成构造器,因为在注入时我们是会带入规则的。以下是相关的代码示例:

    public ZoneAwareLoadBalancer(IClientConfig clientConfig, IRule rule,
                                 IPing ping, ServerList<T> serverList, ServerListFilter<T> filter,
                                 ServerListUpdater serverListUpdater) {
        super(clientConfig, rule, ping, serverList, filter, serverListUpdater);
    }

在这里,当super父类构造器执行完毕后,最终会调用BaseLoadBalancer类的initWithConfig方法。我没有一一追踪下去,但最后ZoneAvoidanceRule的负载均衡代码也相当复杂。不过,你可以将其理解为在没有区域的情况下类似于轮询。

配置多区域情况

在这个阶段,程序将会执行第二个分支,实际上,主要的代码如下所示:

String zone = ZoneAvoidanceRule.randomChooseZone(zoneSnapshot, availableZones);
if (zone != null) {
    BaseLoadBalancer zoneLoadBalancer = getLoadBalancer(zone);
    server = zoneLoadBalancer.chooseServer(key);
}

目的仍然是选择一个服务器,但是限定在当前区域内。关于这部分的详细讨论略去,因为接下来的方法都是关于ZoneAvoidanceRule的负载均衡算法代码。

如何配置其他算法

在这种情况下,如果我想使用其他负载均衡算法而不是当前的算法,应该如何配置呢?实际上,可以查看注入的源代码,有两种方法可以实现这一点。首先,可以通过在配置类中添加一个配置项来指定所需的负载均衡算法。

if (this.propertiesFactory.isSet(IRule.class, name)) {
    return this.propertiesFactory.get(IRule.class, config, name);
}

局部配置

在这里可以看到我们也是通过配置文件来进行配置的,不过配置文件的方式使我们能够进行局部微服务负载均衡的选择。让我们先来看一下源代码:

    public PropertiesFactory() {
        classToProperty.put(ILoadBalancer.class, "NFLoadBalancerClassName");
        classToProperty.put(IPing.class, "NFLoadBalancerPingClassName");
        classToProperty.put(IRule.class, "NFLoadBalancerRuleClassName");
        classToProperty.put(ServerList.class, "NIWSServerListClassName");
        classToProperty.put(ServerListFilter.class, "NIWSServerListFilterClassName");
    }

    public boolean isSet(Class clazz, String name) {
        return StringUtils.hasText(getClassName(clazz, name));
    }

在调用特定的微服务时,可以根据需要使用相应的负载均衡策略来配置 application.yml 文件。

#被调用的微服务名
mall‐order:
 ribbon:
    #指定使用Nacos提供的负载均衡策略(优先调用同一集群的实例,基于随机&权重)
    NFLoadBalancerRuleClassName:com.alibaba.cloud.nacos.ribbon.NacosRule

全局配置

在全局情况下更为简单,可以观察到在自动注入时使用了 @ConditionalOnMissingBean 注解。如果我们在Spring中手动加载了相应的bean,那么这个注解就不会生效了。

    @Bean
    public IRule ribbonRule() {
        // 指定使用Nacos提供的负载均衡策略(优先调用同一集群的实例,基于随机权重)
        return new NacosRule();
    }

相当简单了,那么这样的的话,其实我们也可以进行自定义一个策略的。毕竟照先有的抄下固定实现方法后,自己在实现方法内写上自己的业务逻辑不就完了。

自定义策略

看起来,对于实现其他的负载均衡算法策略,有几个关键点。首先,需要继承 AbstractLoadBalancerRule 父类,并且实现其抽象方法。接下来,我们可以开始编写我们的实现代码:

@Slf4j
public class XiaoYuRandomWithWeightRule extends AbstractLoadBalancerRule { 

    @Override
    public Server choose(Object key) {
        //这里实现自己的逻辑即可
        return server;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}

OK,剩下的就按照局部配置或者全局配置下,让我们的规则生效即可。

在这里只讲述了算法规则的配置和自定义方法,实际上负载均衡器的操作也是类似的套路。这里就不重复演示了。

总结

今天,我们主要补充了上一章关于微服务通信的内容,并深入探讨了负载均衡算法的重要性。我们首先详细讨论了Ribbon默认使用的负载均衡算法。尽管在本地测试时可能会观察到轮询的效果,但简单依赖这种表面的观察是不够的。在真实的生产环境中,特别是在跨多个数据中心部署时,负载均衡策略的选择需要更加深入的理解和分析。

我们进一步分析了如何通过配置和自定义负载均衡规则来灵活应对各种场景。不论是局部配置还是全局配置,我们都能根据具体需求调整负载均衡的行为。同时,我们展示了如何通过自定义算法扩展Ribbon的负载均衡能力,以更好地适应特定业务场景的需求。

在接下来的章节中,我们将深入探讨OpenFeign组件。我们的重点将是如何使开发人员能够更多关注业务逻辑代码,而不是被迫处理与RPC调用相关的繁琐细节。

文章转载自:努力的小雨

原文链接:https://www.cnblogs.com/guoxiaoyu/p/18347224

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

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

相关文章

Superset 无需登录访问分享的图表

1&#xff0c;进入Superset安装目录找到config.py文件 2&#xff0c;修改config.py中的配置项 添加 PUBLIC_ROLE_LIKE: Optional[str] "Gamma" # Grant public role the same set of permissions as for a selected builtin role. # This is useful if one wants to…

Large Bin Attack 源码调试

Large Bin Attack 分配跟 large bin 有关的 chunk&#xff0c;要经过 fastbin&#xff0c;unsorted bin&#xff0c;small bin 的分配&#xff0c;建议在学习 large bin attack 之前搞清楚 fastbin&#xff0c;unsorted bin 分配的流程。 large bin中双向链表的连接方法&…

五款伪原创文章生成器软件,为创作者快速生成高质量内容

在内容为王的时代&#xff0c;创作者们面临着巨大的压力&#xff0c;需要不断地产出高质量、有深度的文章。在这个过程中&#xff0c;伪原创文章生成器软件成为了许多创作者的得力助手。本文将为你详细介绍5款伪原创文章生成器软件&#xff0c;帮助你快速生成高质量内容。 一、…

vue part4

收集表单数据 v-model label直接包住input不用关联也可以获取焦点 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>收集表单数据</title><script type"text/javascript" src&quo…

SpringBoot校园万能墙系统的设计与实现97395

目 录 1 绪论 1.1研究背景与意义 1.2研究现状 1.3论文结构与章节安排 2 相关技术介绍 2.1 springboot框架介绍 2.2 JavaScript 2.3 Mysql数据库 2.4 Vue.js 主要功能 3 系统分析 3.1 可行性分析 3.1.1 技术可行性分析 3.1.2 经济可行性分析 3.1.3 法律可行性分析…

“领导让我帮忙买30杯奶茶,实际花费535元,但领导却只转了500元,我该如何提醒领导转我35元的差额?”

在职场中&#xff0c;我们时常会遇到一些让人哭笑不得的小事&#xff0c;它们虽小&#xff0c;却足以反映出职场中的微妙关系和处事哲学。 一位行政朋友曾发帖称&#xff1a;“我是一名5年工作经验的企业行政助理&#xff0c;也不是小白。但有一次&#xff0c;业务部门领导让我…

【机器学习】嘿马机器学习(科学计算库)第4篇:Matplotlib,学习目标【附代码文档】

本教程的知识点为&#xff1a;机器学习&#xff08;常用科学计算库的使用&#xff09;基础定位 机器学习概述 机器学习概述 1.5 机器学习算法分类 1 监督学习 机器学习概述 1.7 Azure机器学习模型搭建实验 Azure平台简介 Matplotlib 3.2 基础绘图功能 — 以折线图为例 1 完善原…

为什么每个Java开发者都应该掌握CompletableFuture?深入探索这一强大的并发工具!

文章目录 1 如何正确处理异步任务的异常情况&#xff1f;2 如何设置 CompletableFuture 的超时时间&#xff1f;3 如何取消正在执行的CompletableFuture任务&#xff1f; 1 如何正确处理异步任务的异常情况&#xff1f; 想象一下&#xff0c;用餐厅的例子来比喻 CompletableFut…

计算机组成与设计 - 1.7 功耗墙 - 1.8 单处理器向多处理器的转变 - 1.9 基准

1.7 功耗墙 25 年间 1ntel x86 八代微处理器的时钟频率和功耗 。 奔腾 4 处理器时钟频率和功耗提高很大 &#xff0c;但是性能提升不大 。 Prescott 发热问题导致奔腾 4 处理器的生产线被放弃 。 Core 2 生产线恢复使用低时钟频率的简单流水线和片上多处理器 。 Core i5 采用同…

前端常见问题

一、<!DOCTYPE html>作用 <!DOCTYPE>是html文档的第一行&#xff0c;用于声明文档的类型&#xff0c;它会告诉浏览器要用哪一种HTML规范来渲染文档&#xff0c;确保正确渲染页面。 二、src与 href 的区别 &#xff08;一&#xff09;、请求资源类型的不同 在请…

研究生如何利用 ChatGPT 帮助开展日常科研工作?

研究生可以通过以下几种方式利用 ChatGPT 来帮助开展日常科研工作&#xff1a; 文献综述和研究方向&#xff1a;ChatGPT 可以帮助研究生快速了解某一领域的研究现状和热点问题。通过提供相关的文献综述、研究趋势和技术细节&#xff0c;ChatGPT 可以协助确定研究方向和课题。 …

来抄作业!企业财务报表还可以做出这样的可视化效果

从繁琐的手工记账到智能化的数据分析&#xff0c;每一步都标志着企业向更加高效、精准的管理模式迈进。大家可以想象一下&#xff0c;将复杂多变的财务数据以直观、动态的形式展现在眼前的大屏之上&#xff0c;会是一种怎样的体验&#xff1f; 这里就要说到使用山海鲸报表工具搭…

解读2024年国自然资助情况:史上最卷,三无人员也能中

2024年国自然资助情况 面上史上最难&#xff01; 面上项目申请近18万&#xff0c;资助20758项&#xff0c;资助率为11.66%&#xff0c;较2023年下降5.33个百分点。这与今年取消了"申二停一"限制有关&#xff0c;导致资历老的教授、各类人才帽子大量涌入&#xff0c…

昇腾 AscendCL C++应用开发 获取模型的信息

昇腾 AscendCL C应用开发 获取模型的信息 flyfish 举例说明 程序在香橙派 AIpro 下获取到的模型信息 从ACLLite代码里看一些类型&#xff0c;因为获取模型信息的时候&#xff0c;会获取到数字&#xff0c;所以要看数字代表的意思&#xff0c;所有要看常量的名字 数据类型 # …

ch32v307vct6从头移植FreeRTOS

使用官方的ide可以直接创建带FreeRTOS的工程,但是不利于我们学习移植,所以特此记录怎么从头开始移植FreeRTOS到CH32V307VCT6芯片使用。 下载FreeRTOS源码 首先进入https://www.freertos.org/官网,然后找到如下Download字样,进入下载即可 下载完成后我们解压使用。移植开始…

Anzo Capital昂首资本:外汇市场交易策略与平均价格优化

在外汇市场的波动中&#xff0c;Anzo Capital昂首资本通过优化开仓头寸的平均价格&#xff0c;以最小的风险获取最大的利润&#xff0c;致力于帮助投资者实现更精准的交易策略。本文将探讨如何通过策略性地设置订单&#xff0c;来降低平均成本并提高盈利潜力。 Anzo Capital昂…

TypeSript7 class类

ES6提供了更接近传统语言的写法&#xff0c;引入了Class&#xff08;类&#xff09;这个概念&#xff0c;作为对象的模板。通过class关键字&#xff0c;可以定义类。基本上&#xff0c;ES6的class可以看作只是一个语法糖&#xff0c;它的绝大部分功能&#xff0c;ES5都可以做到…

IF 17.3|植物细胞器想发高分文章?你缺的可能是这些内容

文章内容导读 叶绿体和线粒体是唯一拥有内共生起源基因组的细胞器。近年来&#xff0c;测序技术的进步促进了大量植物细胞器基因组的发表&#xff0c;并揭示了它们之间极大的进化轨迹差异。本综述量化了在植物进化树中分布广泛的已测序植物细胞器基因组的数量和分布情况。 文章…

DHCP详解与应用——从原理到实战模拟

1. 引言 在现代网络中&#xff0c;IP地址的自动分配已成为基础设施管理中不可或缺的一部分。动态主机配置协议&#xff08;DHCP&#xff0c;Dynamic Host Configuration Protocol&#xff09;作为一种广泛应用的网络协议&#xff0c;通过自动为设备分配IP地址、子网掩码、网关等…

实用Python自动化脚本案例分享

前言 每天你都可能会执行许多重复的任务&#xff0c;例如阅读新闻、发邮件、查看天气、打开书签、清理文件夹等等&#xff0c;使用自动化脚本&#xff0c;就无需手动一次又一次地完成这些任务&#xff0c;非常方便。而在某种程度上&#xff0c;Python就是自动化的代名词。 1、自…