Ribbon 客户端负载均衡

文章目录

    • 零、懒汉式改为饿汉式
    • 一、基于配置文件
    • 二、基于Bean配置
    • 三、自定义规则
        • 1 权重优先调用
        • 2 集群优先调用
        • 3 元数据优先调用

零、懒汉式改为饿汉式

【consumer-springboot-80子模块】

Ribbon默认使用懒汉式加载服务列表,更改为懒汉式
application.yml

ribbon: # Ribbon相关配置eager-load: # 采用饿汉式进行加载clients: dept.provider # 设置服务名称,使用“,”分割enabled: true # 启用饿汉式

在这里插入图片描述

一、基于配置文件

2、【consumer-springboot-80子模块】

按照SpringCloud 所给出的官方文档来讲,所有Ribbon相关的负载均衡策略全部都可以在application.yml配置文件之中进行定义,对于定义的模型采用的是“ServiceID.ribbon.类型=处理子类”,本次开发之中所使用的“dept.provider”名称就属于一个ServicelD,如果要想为项目进行 application.yml配置就采用如下的方式定义了。

修改application.yml配置文件,追加一个随机访问算法。

dept.provider: # 微服务的IDribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # IRule子类

按照现在所给出的代码的形式应该已经可以成功的进行了访问处理了,所以官方文档所提供的配置项是可以使用的。

3、【consumer-springboot-80子模块】修改application.yml配置文件,追加自定义负载均衡配置实现,现在默认情况下可以见到的负载均衡的算法为“DynamicServerListLoadBalancer”类型,本次配置同样的类型。

dept.provider: # 微服务的IDribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # IRule子类NFLoadBalancerClassName: com.netflix.loadbalancer.DynamicServerListLoadBalancer # ILoadBalancer

二、基于Bean配置

重要提醒:

不要与应用程序组件包重合。虽然之前所有配置的Bean都是放在了SpringBoot启动类的CLASSPATH环境之中,但是Ribbon的配置类不能够放在被直接扫描的路径下,因为会有可能造成配置的冲突。

package muyan.yootk.config.ribbon; // 该包不在应用程序启动类的扫描包路径下import com.netflix.loadbalancer.IRule;
import muyan.yootk.loadbalancer.rule.NacosVersionRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration // 这个类必须使用该注解定义
public class DeptProviderRibbonConfig {@Bean // Bean注册public IRule ribbonRule() { // 自定义负载均衡规则return new RandomRule(); // 随机读取}
}

在没有进行该规则Bean配置的时候,之前采用的是一种轮询的处理模式:按照实例的数量(1,2,3,1,2,3)轮番调用,但是现在变为了随机调用。

package com.yootk.consumer;import muyan.yootk.config.ribbon.DeptProviderRibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableDiscoveryClient
// 如果此时要有多个配置项,可以使用@RibbonClients注解,该注解可以配置多个@RibbonClient
@RibbonClient(name = "dept.provider", configuration = DeptProviderRibbonConfig.class) // 自定义Ribbon配置
@EnableFeignClients("com.yootk.service") // Feign扫描包
public class StartConsumerApplication {public static void main(String[] args) {SpringApplication.run(StartConsumerApplication.class, args);}
}

三、自定义规则

既然在Ribbon里面提供了如此多的默认的规则算法,那么也就可以由用户自己来进行自定义规则算法的使用了,此时直接定义配置Bean即可。

重要提醒:

不要与应用程序组件包重合。虽然之前所有配置的Bean都是放在了SpringBoot启动类的CLASSPATH环境之中,但是Ribbon的配置类不能够放在被直接扫描的路径下,因为会有可能造成配置的冲突。

1 权重优先调用

修改权重可以通过Nacos控制台的模型完成(一般是用于动态修改之中的操作),也可以直接通过微服务application.yml的方式来进行权重的配置。修改完成之后再次通过消费端来进行部门微服务的调用,这个时候发现并没有根据权重的大小来实现定义,这主要是因为Ribbon消费端的负载均衡的算法没有进行有效的配置

1.【provider-dept-*子模块】既然要观察权重可以考虑为所有部门微服务的节点来配置权重的内容,修改每一个微服务之中的application.yml 配置文件,编辑权重的内容:

provider-dept-8001配置:

spring:application: # 配置应用信息name: dept.provider # 是微服务的名称cloud: # Cloud配置nacos: # Nacos注册中心配置discovery: # 发现服务weight: 10

provider-dept-8002配置: weight: 50
provider-dept-8003配置: weight: 80

2、【consumer-springboot-80子模块】创建一个新的负载均衡算法,该算法将基于权重的高低进行调度。

package muyan.yootk.loadbalancer.rule;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;// 如果要想进行规则的定义常见的做法是直接使用IRule接口完成
// 推荐的做法是使用IRule接口对应的抽象子类AbstractLoadBalancerRule
@Slf4j
public class NacosWeightRule extends AbstractLoadBalancerRule { // Nacos权重规则@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties; // Nacos配置属性private IClientConfig clientConfig;@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {this.clientConfig = clientConfig;}@Overridepublic Server choose(Object key) { // 选择服务实例BaseLoadBalancer loadBalancer = (BaseLoadBalancer) super.getLoadBalancer(); // 获取负载均衡器String name = loadBalancer.getName(); // 调用微服务名称// 此时的场景就变为了原生项目的NacosClient组件进行处理的操作了NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance(); // 发现服务// 根据指定的服务名称以及分组名称获取服务的实例try {Instance instance = namingService.selectOneHealthyInstance(name, this.nacosDiscoveryProperties.getGroup());// 整个的代码是工作在SpringCloud之中的,所以需要将获取到的Instance对象实例转为Server对象实例return new NacosServer(instance); // NacosServer是Server子类} catch (NacosException e) {log.error("获取Nacos注册的微服务实例出错,异常为:" + e);return null;}}
}

3、【consumer-springboot-80子模块】DeptProviderRibbonConfig

package muyan.yootk.config.ribbon; // 该包不在应用程序启动类的扫描包路径下import com.netflix.loadbalancer.IRule;
import muyan.yootk.loadbalancer.rule.NacosVersionRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration // 这个类必须使用该注解定义
public class DeptProviderRibbonConfig {@Bean // Bean注册public IRule ribbonRule() { // 自定义负载均衡规则return new NacosWeightRule(); // 随机读取}
}

启动类

package com.yootk.consumer;import muyan.yootk.config.ribbon.DeptProviderRibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableDiscoveryClient
// 如果此时要有多个配置项,可以使用@RibbonClients注解,该注解可以配置多个@RibbonClient
@RibbonClient(name = "dept.provider", configuration = DeptProviderRibbonConfig.class) // 自定义Ribbon配置
@EnableFeignClients("com.yootk.service") // Feign扫描包
public class StartConsumerApplication { // 沐言科技:www.yootk.compublic static void main(String[] args) {SpringApplication.run(StartConsumerApplication.class, args);}
}

2 集群优先调用

1、【consumer-springboot-80子模块】NacosClusterWeightRule

package muyan.yootk.loadbalancer.rule;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;@Slf4j
public class NacosClusterWeightRule extends AbstractLoadBalancerRule {// 如果要想按照集群调用,那么首先一定要知道当前消费端的集群名称是什么@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties; // 注入Nacos发现服务配置项@Autowiredprivate IClientConfig clientConfig;@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {this.clientConfig = clientConfig;}@Overridepublic Server choose(Object key) { // 核心关键BaseLoadBalancer loadBalancer = (BaseLoadBalancer) super.getLoadBalancer();// 如果此时没有这个调用的微服务名称,那么是无法实现最终的服务查询的String name = loadBalancer.getName();// 获取服务名称NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();// 获取指定服务名称的全部的实例列表数据try {// 根据指定的服务名称以及分组查询所有健康的服务实例列表,此时的列表包含有所有的集群信息List<Instance> instances = namingService.selectInstances(name, this.nacosDiscoveryProperties.getGroup(), true);// 理论上现在应该采用的是迭代的处理形式,将全部的集合列表进行迭代处理,随后进行集群名称的判断List<Instance> clusterInstance = instances.stream().filter(instance -> Objects.equals(instance.getClusterName(), this.nacosDiscoveryProperties.getClusterName())).collect(Collectors.toList());List<Instance> instancesChoose = null; // 保存最终的返回的列表// 如果以上的处理可以获取指定集群名称下的全部的服务实例数据,那么就可以随意返回一个,但是如果不能够获取?if (CollectionUtils.isEmpty(clusterInstance)) { // 此时集群下的实例列表为空// 此时在指定集群名称下没有查找到任何的实例列表,所以就把所获取到的全部实例列表instancesChoose = instances;} else { // 如果已经查找到了指定集群名称下的实例列表instancesChoose = clusterInstance; // 保存集群实例列表}// 因为最终所需要的是一个Server实例信息,所以这个时候可以考虑随机读取一个,或者按照权重返回一个Instance selectedInstance = ExtendBalancer.getHostByRandomWeight2(instancesChoose);return new NacosServer(selectedInstance); // 指定集群名称下的一个实例} catch (NacosException e) {log.error("服务实例查询时出现了错误,异常为:{}", e);}return null;}
}

2、【consumer-springboot-80子模块】DeptProviderRibbonConfig

package muyan.yootk.config.ribbon; // 该包不在应用程序启动类的扫描包路径下import com.netflix.loadbalancer.IRule;
import muyan.yootk.loadbalancer.rule.NacosVersionRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration // 这个类必须使用该注解定义
public class DeptProviderRibbonConfig {@Bean // Bean注册public IRule ribbonRule() { // 自定义负载均衡规则return new NacosClusterWeightRule (); // 随机读取}
}

3 元数据优先调用

1、【consumer-springboot-80子模块】NacosVersionRule

package muyan.yootk.loadbalancer.rule;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;@Slf4j
public class NacosVersionRule extends AbstractLoadBalancerRule {// 如果要想按照集群调用,那么首先一定要知道当前消费端的集群名称是什么@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties; // 注入Nacos发现服务配置项@Autowiredprivate IClientConfig clientConfig;@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {this.clientConfig = clientConfig;}@Overridepublic Server choose(Object key) {BaseLoadBalancer loadBalancer = (BaseLoadBalancer) super.getLoadBalancer();// 如果此时没有这个调用的微服务名称,那么是无法实现最终的服务查询的String name = loadBalancer.getName();// 获取服务名称NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();try {// 根据指定的服务名称以及分组的名称获取全部的可用实例数据List<Instance> instances = namingService.selectInstances(name, this.nacosDiscoveryProperties.getGroup(), true);// 对获取到的实例集合进行迭代处理,筛选出所需要的与当前版本匹配的实例数据List<Instance> metadataVersionMatchInstance = instances.stream().filter(instance -> Objects.equals(this.nacosDiscoveryProperties.getMetadata().get("version"), // 消费端配置的元数据版本项instance.getMetadata().get("version"))) // 注册微服务实例配置的元数据版本项.collect(Collectors.toList());// 必须考虑没有匹配版本下的实例筛选操作List<Instance> selectedInstances = null; // 最终所使用的实例集合if (CollectionUtils.isEmpty(metadataVersionMatchInstance)) {    // 没有查询到匹配的集合selectedInstances = instances;} else {selectedInstances = metadataVersionMatchInstance; // 版本匹配}Instance instance = ExtendBalancer.getHostByRandomWeight2(selectedInstances);return new NacosServer(instance);} catch (NacosException e) {log.error("获取Nacos注册的微服务实例出错,异常为:" + e);}return null;}
}

3、【consumer-springboot-80子模块】DeptProviderRibbonConfig

package muyan.yootk.config.ribbon; // 该包不在应用程序启动类的扫描包路径下import com.netflix.loadbalancer.IRule;
import muyan.yootk.loadbalancer.rule.NacosVersionRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration // 这个类必须使用该注解定义
public class DeptProviderRibbonConfig {@Bean // Bean注册public IRule ribbonRule() { // 自定义负载均衡规则return new NacosVersionRule (); // 随机读取}
}

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

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

相关文章

C#使用Xamarin开发可移植移动应用(3.Xamarin.Views控件)附源码

.NET core2.0 发布了,刺激,大致看了一下,很不错,打算后期学习.(不出意外,应该也会写个小系列). 虽然官方推荐用共享类库创建新的类库..然而我这个Demo还是使用的可移植.. 嗯..解释一下 为什么暂时没用共享类库.. 有些小BUG 可能是为了迎合其他类型的项目..所以在共享类库里创…

“老师,我不要苹果味的,我要葡萄味的”!

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。题库四班目前题库正在维护中&#xff0c;工作量最大的莫过于题库里面的题量了&#xff0c;所以目前的解决方法是让动员大家一起出题&#xff0c;但是人多较杂&#xff0c;各种各样的题都有&#xff08;…

一次频繁Full GC的排查过程,根源居然是它...

转载自 一次频繁Full GC的排查过程&#xff0c;根源居然是它... 业务部门的一个同事遇到个奇怪的 Full GC 问题&#xff0c;有个服务迁移到新的应用后&#xff0c;一直频繁 Full GC。新应用机器的配置是 4c 8g&#xff0c;老应用是 4c 4g&#xff0c;老应用 GC 都很正常&…

jzoj1158-荒岛野人【扩欧,gcd,同余方程】

正题 大意 有n个野人&#xff0c;每个野人有一个初始山洞CiCi&#xff0c;每次向前移动距离PiPi&#xff0c;寿命LiLi&#xff0c;如果野人走到了最后一个山洞那么继续就好回到第一个山洞&#xff0c;求至少多少个山洞才可以让野人们不会发生冲突。 解题思路 我们可以枚举答…

.NET Core 2.0 的dll实时更新、https、依赖包变更问题及解决

今天所有开发环境已经迁移到mac OS下的Visual Studio Code 命令行编译发布&#xff0c;而运行服务器是CentOS7&#xff0c;和windows没什么关联了。 只要你Relese编译并在本地有一个与服务器相同的运行环境中运行成功了&#xff0c;迁移到真实服务器不会有什么难度。 下面是迁…

“老师,我写着写着就 强制交卷了……”

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。01暴露出的问题

张老师讲Python~

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号【雄雄的小课堂】。最近我的个人站上线啦&#xff0c;欢迎大家访问http://穆雄雄.com&#xff1b;或者点击文末的“阅读原文”。昨天下午靳老师分享了关于网站部署的内容&#xff0c;今天下午请张炜林上去分享了下他准…

Entity Framework Core 2.0 新特性

一.模型级查询过滤器&#xff08;Model-level query filters&#xff09; ef core2.0包含了一个新特性&#xff0c;我们叫他模型级查询过滤器&#xff08;Model-level query filters&#xff09;。此特性允许使用Linq查询表达式直接定义在实体类型的元数据模型上。这样的过滤器…

激动的时刻,终于成啦~

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号&#xff1a;【雄雄的小课堂】。今天&#xff0c;最令我激动的一件事莫过于倾注一周精力的“在线测试”终于可以投入使用了&#xff0c;周二发过一篇文章&#xff0c;是关于在线测试的问题总结&#xff0c;也就是在周二&a…

C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码

今天的学习内容? 今天我们讲讲Xamarin中的MVVM双向绑定,嗯..需要有一定的MVVM基础.,具体什么是MVVM - -,请百度,我就不多讲了 效果如下: 正文 1.简单的入门Demo 这个时间的功能很简单,就是一个时间的动态显示. 我们首先创建一个基础的页面如下: <?xml version"…

由「Metaspace容量不足触发CMS GC」从而引发的思考

转载自 由「Metaspace容量不足触发CMS GC」从而引发的思考 某天早上&#xff0c;毛老师在群里问「cat 上怎么看 gc」。 好好的一个群 看到有 GC 的问题&#xff0c;立马做出小鸡搓手状。 之后毛老师发来一张图。 老年代内存占用情况 图片展示了老年代内存占用情况。 第一个…

是现在的钱不值钱还是药太贵!

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号【雄雄的小课堂】。莫名其妙的就感觉身体不舒服&#xff0c;然后越来越严重&#xff0c;打小以来还是第一次遇见这样的&#xff0c;你说是感冒吧&#xff0c;它也不流鼻涕&#xff0c;喉咙也不痛&#xff0c;鼻子也通…

一次堆外内存泄露的排查过程

转载自 一次堆外内存泄露的排查过程 最近在做一个基于 websocket 的长连中间件&#xff0c;服务端使用实现了 socket.io 协议&#xff08;基于websocket协议&#xff0c;提供长轮询降级能力&#xff09; 的 netty-socketio 框架&#xff0c;该框架为 netty 实现&#xff0c;鉴…

.NET Core 2.0 特性介绍和使用指南

前言 这一篇会比较长&#xff0c;介绍了.NET Core 2.0新特性、工具支持及系统生态&#xff0c;现状及未来计划&#xff0c;可以作为一门技术的概述来读&#xff0c;也可以作为学习路径、提纲来用。 对于.NET Core 2.0的发布介绍&#xff0c;围绕2.0的架构体系&#xff0c;我想…

Lombok MyBatisX

Lombok的使用 [1] 什么是LomBok lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具&#xff0c;简单来说&#xff0c;比如我们新建了一个类&#xff0c;然后在其中写了几个属性&#xff0c;然后通常情况下我们需要手动去建立g…

一次堆外OOM问题的排查过程

转载自 一次堆外OOM问题的排查过程 背景 线上服务有一台机器访问不通&#xff08;一个管理平台),在公司的服务治理平台上查看服务的状况是正常的&#xff0c;说明进程还在。进程并没有完全crash掉。去线上查看机器日志&#xff0c;发现了大量的OOM异常: 017-03-15 00:00:0…

Azure与Scott Guthrie:Azure安全中心和基于角色的访问控制

InfoQ有幸采访了Microsoft执行副总裁Scott Guthrie&#xff0c;请他谈了谈Azure以及他最近的Red Shirt Dev Tours&#xff08;红杉开发之旅&#xff09;【译注1】。昨天我们谈到了Azure提供了自定义仪表盘的功能&#xff0c;它能够使得开发者创建自定义工作任务流程&#xff0c…

什么时候才能都及格呢?

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。今天是周五&#xff0c;又到了周测的时候了&#xff0c;发现现在考试&#xff0c;学生们的抵触情绪不会那么强烈了&#xff0c;以前只要一说啥时啥时考试&#xff0c;下面一片哀嚎声&#xff0c;各种不…

解决Visual Studio For Mac Restore失败的问题

之前就了解到微软出了mac版的VS&#xff0c;没太多的关注&#xff0c;自己也就是使用 DotNet Core SDK VS Code 做一些小demo。 前两天发布了DotNet Core 2.0 &#xff0c;Visual Studio For Mac 7.1 之后&#xff0c;感觉可以装起来用用&#xff0c;把win下面的项目转到Core…

来之不易的美团面试,结果居然挂了...(附面试答案)

转载自 来之不易的美团面试&#xff0c;结果居然挂了...&#xff08;附面试答案&#xff09; 一面 自我介绍 答&#xff1a;自我介绍是面试中唯一的自己主动介绍自己的环节&#xff0c;一定要好好把握好&#xff0c;你数据结构学的号可以手撕一个红黑树你就说我数据结构掌握…