SpringCloud之LoadBalancer自定义负载均衡算法,基于nacos权重

news2024/12/23 13:29:27

LoadBalancer基于Nacos权重自定义负载算法

ReactorLoadBalancer接口,实现自定义负载算法需要实现该接口,并实现choose逻辑,选取对应的节点

public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {
    Mono<Response<T>> choose(Request request);

    default Mono<Response<T>> choose() {
        return this.choose(REQUEST);
    }
}

RoundRobin算法核心源码

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + this.serviceId);
            }

            return new EmptyResponse();
        } else {
            //通过cas的position变量自增,循环 % 实例数。
            int pos = Math.abs(this.position.incrementAndGet());
            ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
            return new DefaultResponse(instance);
        }
    }

nacos权重

nacos可以配置不同实例的权重信息,可以在

  1. yaml中配置spirng.cloud.nacos.discovery.weight 数值范围从1-100 ,默认为1
  2. 可以在nacos面板找到该实例信息,并实时配置实例的权重

在这里插入图片描述

在这里插入图片描述

基于nacos权重实现自定义负载

权重:数值越高,代表被选取的概率越大.

根据RoundRobin源码,自定义NacosWeightLoadBalancer

package cn.axj.loadbalancer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.*;
import reactor.core.publisher.Mono;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 基于nacos权重的负载均衡
*/
public class NacosWeightLoadBalancer implements ReactorServiceInstanceLoadBalancer {

    private static final Log log = LogFactory.getLog(NacosWeightLoadBalancer.class);
    private final String serviceId;
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

    //nacos权重获取名称,在nacos元数据中
    private static final String NACOS_WEIGHT_NAME = "nacos.weight";

    public NacosWeightLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        ServiceInstanceListSupplier supplier = this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
        return supplier.get(request).next().map((serviceInstances) -> {
            return this.processInstanceResponse(supplier, serviceInstances);
        });
    }


    private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances) {
        Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(serviceInstances);
        if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
            ((SelectedInstanceCallback)supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
        }

        return serviceInstanceResponse;
    }


    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            if (log.isWarnEnabled()) {
                log.warn("No servers available for service: " + this.serviceId);
            }
        } else {
            //根据权重选择实例,权重高的被选中的概率大
            //nacos.weight的值越大,被选中的概率越大
            Double totalWeight = 0D;
            for (ServiceInstance instance : instances) {
                String s = instance.getMetadata().get(NACOS_WEIGHT_NAME);
                double weight = Double.parseDouble(s);
                totalWeight = totalWeight + weight;
                //放置当前实例的权重区间
                instance.getMetadata().put("weight",String.valueOf(totalWeight));
            }
            //随机获取一个区间类的数值,nacos权重越大,区间越大,则随机数值落到相应的区间的概率是由区间的大小来决定的。
            double index = ThreadLocalRandom.current().nextDouble(totalWeight);
            //根据权重区间选择实例
            for (ServiceInstance instance : instances) {
                double weight = Double.parseDouble(instance.getMetadata().get("weight"));
                if (index <= weight) {
                    return new DefaultResponse(instance);
                }
            }

        }
        return new EmptyResponse();
    }
}

配置使用

增加WeightLoadBalanceConfiguration

public class WeightLoadBalanceConfiguration {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> weightLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new NacosWeightLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}

修改主类配置

@LoadBalancerClients({
        @LoadBalancerClient(name = "loadbalance-provider-service", configuration = WeightLoadBalanceConfiguration.class)
})

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

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

相关文章

(一)基于IDEA的JAVA基础16(end)

二维数组 二维数组就是数组里面再放一个数组 语法: <数据类型> [] [] 数组名&#xff1b; 或: <数据类型> 数组名 [] []&#xff1b; 比如这里有5个单位&#xff0c;每个单位员工有20个&#xff0c;他们都在忙几个相同的项目&#xff0c;现在要对某项项目进行操…

js 写 视频轮播

html代码 <div class"test_box"> <div class"test"> <a href"#"> <div class"test_a_box"> <div class"test_a_mask"></div> <div class"test_a_layer"> <div cla…

2024蓝桥A组D题

团建 问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序难度等级 问题描述 格式输入 输入的第一行包含两个正整数n,m&#xff0c;用一个空格分隔。 第二行包含n个正整数c1,c2, ,cn&#xff0c;相邻整数之间使用一个空格分隔&#xff0c; 其中ci表示第一…

idea新建一个springboot项目

本文分为几个部分&#xff0c; 首先是在idea中新建项目&#xff0c; 然后是配置 项目的目录&#xff08;新建controller、service、dao等&#xff09;&#xff0c; 然后是自定义的一些工具类&#xff08;比如启动后打印地址等&#xff09;。 1.、创建篇 新建项目&#xff0…

毕设选51还是stm32?51太简单?

如果你更倾向于挑战和深入学习&#xff0c;STM32可能是更好的选择。如果你希望更专注于底层硬件原理&#xff0c;51可能更适合。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff…

bestvike 资料 --Spring Boot 2.5.0

Spring Boot 2.5.0 SSM环境搭建 springspringmvcmybatisspring springmvc mybatis # 项目 - 需求分析 概要设计(库表设计) 详细设计(验证库表正确性) 编码(环境搭建业务代码) 测试 部署上线# 员工添加 查询所有功能 SSM - 库表 库: ssm 数据库:mysql 表: id na…

【教程】将Vue项目打包为exe项目的教程-我的第一个原生Vue项目

文章目录 前言项目介绍正文&#xff1a;Vue打包exe过程及注意事项1. &#xff08;重要&#xff09;进入我们自己的项目&#xff0c;修改公共路径为相对路径2. &#xff08;重要&#xff09;关于VueRouter的必要修改3. 前端打包4. 拉取electron-quick-start项目5. 修改配置文件6…

【高阶数据结构】哈希表 {哈希函数和哈希冲突;哈希冲突的解决方案:开放地址法,拉链法;红黑树结构 VS 哈希结构}

一、哈希表的概念 顺序结构以及平衡树 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系。因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff1b;平衡树中为树的高度&#xff0c;即O(log_2 N)&#xf…

【python】项目实战

启动一个项目对于新手都是不容易的事情 在哪 对于Windows平台&#xff0c;打开cmd 使用命令py -0p 【其中0是零】 显示已安装的 python 版本且带路径的列表 切换python3命令 在Windows下&#xff0c;可以使用cmd下使用mklink命令创建“软链接”更好一些。 例如&#xf…

weblogic oracle数据源配置

在weblogic console中配置jdbc oracle数据源 1. base_domain->Service->DataSources 在Summary of JDBC Data Sources中&#xff0c;点击New, 选择【Generic Data Source】通用数据源。 2. 设置数据源Name和JNDI name 注&#xff1a;设置的JNDI Name是Java AP中连接…

正则匹配密码 - 使用正向先行断言

代码 import redef password_is_ok(password: str) -> bool:"""1. 密码只能是字母数字组合2. 密码必须包含大小写字母以及数字"""result re.findall(^(?.*\d)(?.*[a-z])(?.*[A-Z])[0-9a-zA-Z]{8,16}$, password)return True if result e…

HCIP的学习(9)

OSPF的接口网络类型 ​ OSPF的接口在某种网络类型下的工作方式。 网络类型OSPF接口的工作方式BMABroadcast&#xff1b;可以建立多个邻居关系。需要进行DR选举。hello 10S&#xff1b;dead 40S。P2PP2P&#xff1b;只能建立一个邻居关系&#xff0c;不需要进行DR选举。Hello …

语音智能客服机器人有什么优势?ai机器人部署

人工智能技术的进步&#xff0c;在不断的革新我们的工作和生活&#xff0c;同时&#xff0c;拥有人工智能技术的语音智能客服机器人在销售行业的工作熟悉程度也越来越好&#xff0c;那语音智能客服机器人有什么优势&#xff1f;我们一起来看看。 1、ASR语音文本转换 客户可通过…

量子城域网系列(四):几种典型的量子密钥分发网络组网方案

通过之前的文章&#xff0c;我们对点对点的量子保密通信网络有了直观的认识&#xff0c;也知道了量子保密通信系统就是利用量子密钥分发产生的无条件安全量子密钥作为系统安全性保证。所以在实际应用中&#xff0c;一个通信网络如果想实现量子加密&#xff0c;就需要建设量子密…

计算机网络3——数据链路层1

文章目录 一、介绍1、基础2、内容 二、数据链路层的几个共同问题1、数据链路和帧2、三个基本问题1&#xff09;封装成帧2&#xff09;透明传输3&#xff09;差错检测 三、点对点协议 PPP1、PPP协议的特点1&#xff09;PPP 协议应满足的需求2&#xff09;PPP 协议的组成 2、PPP协…

Redis入门到通关之ZSet命令

文章目录 ⛄概述⛄常见命令有⛄RedisTemplate API❄️❄️ 向集合中插入元素&#xff0c;并设置分数❄️❄️向集合中插入多个元素,并设置分数❄️❄️按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部❄️❄️获得指定元素的分数❄️❄️返回集合内的成员个数❄️❄…

6. Django 深入模板

6. 深入模板 6.1 Django模板引擎 Django内置的模板引擎包含模板上下文(亦可称为模板变量), 标签和过滤器, 各个功能说明如下: ● 模板上下文是以变量的形式写入模板文件里面, 变量值由视图函数或视图类传递所得. ● 标签是对模板上下文进行控制输出, 比如模板上下文的判断和循…

SpringCloud之LoadBalancer负载均衡器的简单使用

SpringCloud之LoadBalancer负载均衡器的简单使用 loadbalancer用于对提供服务的集群做一个节点的选取规则。 如图所示&#xff0c;load balancer集成在调用方 示例 创建loadbalance-base模块,并引入相关依赖 <dependencies><dependency><groupId>org.spr…

SVN泄露(ctfhub)

目录 下载安装dvcs-ripper 使用SVN 一、什么是SVN&#xff1f; 使用SVN能做什么&#xff1f; 二、SVN泄露&#xff08;ctfhub&#xff09; SVN源代码漏洞的主要原因&#xff1a; 工具准备&#xff1a;dirsearch、dvcs-ripper 网络安全之渗透测试全套工具篇&#xff08;内…

GPT的使用

个人笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 个人随笔&#xff1a;工作总结随笔_8、以前工作中都接触过哪些类型的测试文档-CSDN博客 网站sms-activate.or…