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

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
EMR Serverless StarRocks,5000CU*H 48000GB*H
网络型负载均衡 NLB,每月750个小时 15LCU
简介: ReactorLoadBalancer接口,实现自定义负载算法需要实现该接口,并实现choose逻辑,选取对应的节点。

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)
})

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
2月前
|
负载均衡 算法 Java
Spring Cloud全解析:负载均衡算法
本文介绍了负载均衡的两种方式:集中式负载均衡和进程内负载均衡,以及常见的负载均衡算法,包括轮询、随机、源地址哈希、加权轮询、加权随机和最小连接数等方法,帮助读者更好地理解和应用负载均衡技术。
|
8天前
|
运维 负载均衡 安全
|
17天前
|
负载均衡 算法
SLB-Backend的负载均衡算法
【10月更文挑战第19天】
35 5
|
3月前
|
算法 NoSQL Java
spring cloud的限流算法有哪些?
【8月更文挑战第18天】spring cloud的限流算法有哪些?
88 3
|
3月前
|
负载均衡
alb负载均衡按量降价了,资源包抵扣已经比按量付费的贵了,结果还是在走资源包抵扣。
ALB实例按量付费已降价,1万LCU资源包单价现为0.0485,3LCU可抵一小时标准版实例费用(原0.147现降至0.125),单LCU价格也下调至0.042。资源包价格保持不变,旧购资源包仍在抵扣中,建议调整为降价时不进行抵扣。同时,附上与不太了解情况的客服交流记录供参考。
|
4月前
|
负载均衡 算法 应用服务中间件
nginx自定义负载均衡及根据cpu运行自定义负载均衡
nginx自定义负载均衡及根据cpu运行自定义负载均衡
84 1
|
3月前
|
负载均衡 Cloud Native 容灾
阿里云负载均衡SLB价格_ALB、NLB和CLB区别_负载均衡详细介绍
阿里云负载均衡SLB提供ALB、NLB和CLB三种类型,分别适用于7层和4层的不同场景。ALB与NLB仅支持按量付费,而CLB则额外提供包年包月选项。ALB强调7层应用处理与高级路由,NLB聚焦4层的大流量处理与SSL卸载。两者均支持自动弹性伸缩,确保高可用性和性能。CLB作为传统负载均衡,适用于特定需求。每种类型依据实例规格与使用量收费,其中公网实例还需支付网络费用。通过这些服务,用户可以实现流量分发、故障转移及提升应用系统的稳定性和扩展性。
|
3月前
|
负载均衡 前端开发 数据处理
"揭秘!ALB负载均衡器如何赋能Airflow,让数据处理命令请求在云端翩翩起舞,挑战性能极限,你不可不知的秘密!"
【8月更文挑战第20天】在现代云计算环境中,负载均衡ALB作为七层HTTP/HTTPS流量分发器,能显著提升系统的可用性和扩展性。结合Airflow这一开源工作流管理平台,ALB可以有效分发其REST API命令请求。通过配置ALB实例监听HTTP/S请求,并将多个Airflow实例加入目标组,再配合健康检查确保实例稳定,即可实现对Airflow命令的高效负载均衡,进而增强数据处理任务的可靠性和性能。
38 0
|
3月前
|
负载均衡 Cloud Native 容灾
阿里云负载均衡SLB价格_ALB、NLB和CLB区别_负载均衡功能和使用场景说明
阿里云负载均衡SLB分为应用型ALB、网络型NLB及传统型CLB。ALB与NLB仅支持按量付费,而CLB则提供包年包月和按量付费选项。ALB专长于7层HTTP/HTTPS/QUIC协议处理,支持丰富的内容路由功能;NLB聚焦于4层TCP/UDP/TCPSSL协议,擅长处理大规模并发连接。两者均基于NFV技术,支持自动弹性伸缩,并与云原生环境如ACK/SAE/K8S深度集成。此外,SLB提供多协议支持、多级容灾、安全防护等功能,确保服务的高可用性和安全性。具体收费方面,ALB的基础版实例费为0.049元/小时起,NLB实例费限时免费,两者还需支付性能容量单位LCU费及公网网络费(仅公网实例)
|
5月前
|
机器学习/深度学习 算法
**反向传播算法**在多层神经网络训练中至关重要,它包括**前向传播**、**计算损失**、**反向传播误差**和**权重更新**。
【6月更文挑战第28天】**反向传播算法**在多层神经网络训练中至关重要,它包括**前向传播**、**计算损失**、**反向传播误差**和**权重更新**。数据从输入层流经隐藏层到输出层,计算预测值。接着,比较预测与真实值计算损失。然后,从输出层开始,利用链式法则反向计算误差和梯度,更新权重以减小损失。此过程迭代进行,直到损失收敛或达到训练次数,优化模型性能。反向传播实现了自动微分,使模型能适应训练数据并泛化到新数据。
69 2