您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

详谈负载均衡算法

时间:2023-03-21 15:12:10  来源:  作者:Java灵风

前言


19年我几乎把阿里很多部门都面过,那一年也是行情最好的一年,icbu、uc、淘系、乌鸫、ae、上海支付宝(刚好有朋友在那),那会真的惨烈,被摁在地上摩擦,不过我也因此全方面的对自己有了一次认识,知道了基础知识(八股文)不熟,在技术深度上欠缺。最后是拿了淘系的offer,不容易啊~

每次面试都是对过往的review,也是自我提升的垫脚石

最近在搞流量负载相关的东西,顺便就温故下负载均衡算法,然后也玩了一下ChatGPT,发现很强大,给的代码demo都很详细,感觉百度都可有可无了,hhh

 

负载均衡算法有哪些


 

我感觉可以让gpt帮我写篇文章了,笑死。

  1. 轮训
  2. 随机
  3. 最小活跃数
  4. 权重
  5. 自适应 6.so on...

前两个我们就不用说了,从第三点来聊聊

最小活跃数

什么是活跃数?它储存在哪里?为什么要这么做?

这里的活跃数指的是dubbo连接数,就是客户端对服务端的连接数有多少,它会优先指向连接数小的。它储存在客户端,也就是说每次请求会给连接+1,释放的时候又会-1。为什么这么做呢?为了分摊压力,让空闲的服务端多接点流量。

逻辑:从客户端的记录里面搂出哪个服务端连接数最小,如果有并列则看权重,如果权重一样则随机。

public class LeastActiveLoadBalance extends AbstractLoadBalance {
    public static final String NAME = "leastactive";

    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        int length = invokers.size(); // 总个数
        int leastActive = -1; // 最小的活跃数
        int leastCount = 0; // 相同最小活跃数的个数
        int[] weights = new int[length]; // 权重
        int totalWeight = 0; // 总权重
        for (int i = 0; i < length; i++) {
            Invoker<T> invoker = invokers.get(i);
            int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // 活跃数
            int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT); // 权重
            if (leastActive == -1 || active < leastActive) { // 发现更小的活跃数,重新开始
                leastActive = active; // 记录最小活跃数
                leastCount = 1; // 重新统计相同最小活跃数的个数
                weights[0] = weight; // 将当前权重记录下来,留作备选
                totalWeight = weight; // 初始化总权重
            } else if (active == leastActive) { // 累计相同最小的活跃数
                weights[leastCount++] = weight; // 将当前权重记录下来,留作备选
                totalWeight += weight; // 累加权重
            }
        }
        if (leastCount == 1) { // 如果只有一个最小则直接返回
            return invokers.get(0);
        }
        // 如果权重不相等且权重大于0则按权重分配,否则随机分配
        return selectByRandomWeight(invokers, weights, totalWeight);
    }
}

复制代码

加权负载

这个就是我们人为给这些dubbo服务端加上权重,这样做的好处就是我们本来就是知道那台服务器配置比较牛,它可以承受更多的请求,这样我们让流量更多的打到它上面,更好利用资源。

基于rt自适应负载均衡

这个一开始我在博客看到的,就是讲dubbo3对这块会有关于cpu还有类似rt相关自适应的负载均衡

我看阿里的天池比赛中,看到这样一个根据rt来做负载均衡的,大家可以观摩一哈

  • [complone/dubbo-loadbalance](Github.com/complone/du…)
package com.aliware.tianchi;

import org.Apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.LoadBalance;

import com.aliware.tianchi.comm.CustomerInfo;

import JAVA.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author complone
 */
public class UserLoadBalance implements LoadBalance {

    @Override
    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {

        //1、所有服务器争取每个打一次请求
        Invoker invoker = doSelectInFreeInvokers(invokers);

        //2、根据服务端信息分配权重
        invoker = invoker != null ? invoker : doSelectWithWeigth(invokers);

        return invoker;
    }

    /**
     * 落实优先每个机器都有流量请求
     */
    private <T> Invoker<T> doSelectInFreeInvokers(List<Invoker<T>> invokers) {

        if (CustomerInfoManager.LOAD_INFO.size() < invokers.size()) {
            for (Invoker invoker : invokers) {

                CustomerInfo customerInfo = CustomerInfoManager.getServerLoadInfo(invoker);

                if (customerInfo != null) break;

                return invoker;
            }
        }

        return null;
    }

    /**
     * 根据服务端配置和平均耗时计算权重
     */
    private <T> Invoker<T> doSelectWithWeigth(List<Invoker<T>> invokers) {

        // 重新分配权重的<服务,权重>映射
        int[] serviceWeight = new int[invokers.size()];

        // 总权重
        int totalWeight = 0;

        // 1、计算总权重
        for (int index = 0, size = invokers.size(); index < size; ++index) {

            Invoker<T> invoker = invokers.get(index);

            CustomerInfo customerInfo = CustomerInfoManager.getServerLoadInfo(invoker);
            AtomicInteger avAIlThreadAtomic = CustomerInfoManager.getAvailThread(invoker);

            if (customerInfo != null) {

                if (availThreadAtomic.get() > 0) {
                    int weight = customerInfo.getServerWeight();
                    //根据耗时重新计算权重(基本权重*(1秒/单个请求耗时))
                    int clientTimeAvgSpendCurr = customerInfo.getAvgSpendTime();
                    if (clientTimeAvgSpendCurr == 0) {
                        // 耗时为0,性能优,请求直接打到该机器
                        // 也有可能是性能差,采用随机
                        return invokers.get(ThreadLocalRandom.current().nextInt(invokers.size()));
                    }

                    // 计算权重
                    weight = weight * (500 / clientTimeAvgSpendCurr);
                    serviceWeight[index] = weight;
                    totalWeight = totalWeight + weight;
                }
            }
        }

        // 2、按照新的权重选择服务,权重加权随机算法
        int oneWeight = ThreadLocalRandom.current().nextInt(totalWeight);

        for (int i = 0, size = invokers.size(); i < size; ++i) {
            oneWeight -= serviceWeight[i];
            if (oneWeight < 0) {
                return invokers.get(i);
            }
        }

        //兜底采用随机算法
        return invokers.get(ThreadLocalRandom.current().nextInt(invokers.size()));
    }
}
复制代码

首先是
customerInfo.getAvgSpendTime(),就是客户端会保持每个服务端请求次数、总的请求时间,这样平均响应时间就出来了,这里为什么要用500去除,而不是其他数字呢?我没有仔细看内部细节,当分母越大,这个数越小,也就是rt越长,服务节点性能越差,对应的权重会越小,这个思想我们还是能理解的。

int oneWeight = ThreadLocalRandom.current().nextInt(totalWeight); 
for (int i = 0, size = invokers.size(); i < size; ++i) { 
    oneWeight -= serviceWeight[i]; 
    if (oneWeight < 0) { 
        return invokers.get(i); 
     } 
}
复制代码

这块有点意思了,大家看得懂吗?让我想起之前抽奖算法,比如说a商品有40%,b商品有60%几率,怎么去抽奖呢?

同比比例扩大,比如说a有4个商品,b有6个商品,你去随机抽一个,是不是有那味了,哈哈。同样这里也是,就是我们把所有服务器节点的权重拿到了,总计一个总的权重,然后我们生成一个随机数,那么看它最后是命中那个节点,当权重大的它会更有几率命中,是这么个意思~

那基于cpu呢?

基于cpu自适应负载均衡

 

最重要就这些数据指标怎么拿到,chatgpt已经跟我讲了,可以通过grafana类似运维监控工具来提供,如何跟dubbo结合起来?如果这些数据没有拿到怎么兜底?

这个思路可以参考服务注册中心,其实就是pingpong,异步定期去拉取数据然后存到本地缓存里面,具体拉取的频率怎样,根据实际情况决定要多久去拉取,其次是访问量,比如说有很多节点请求次数频繁,那么就启用缓存,先把数据存缓存,dubbo直接读取缓存数据即可。最后兜底方案比如说读不到服务cpu值,那么直接换负载算法兜底。

总结


流量负载算法是一种常用的负载均衡策略,它可以将网络流量分配到多个服务器上,从而提高系统的性能和可靠性。常见的流量负载算法包括轮询、加权轮询、最小连接数等。在选择合适的负载均衡算法时,需要考虑服务器的性能、网络拓扑结构以及用户访问模式等因素。同时,为了保证系统的可靠性,需要采取故障转移和容错机制。


原文链接:
https://juejin.cn/post/7212616585768009787



Tags:算法   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
诱导付费、自动扣费……微短剧被质疑借助算法精准“围猎”老年人
诱导付费、自动扣费、重复收费&hellip;&hellip;聚焦身边的消费烦心事⑦丨一些微短剧被质疑借助算法精准“围猎”老年人中工网北京3月31日电(工人日报&mdash;中工网记者刘兵)...【详细内容】
2024-04-01  Search: 算法  点击:(6)  评论:(0)  加入收藏
分析网站SEO快速排名算法对网站具体的影响效果
亲爱的朋友们,今天我想和大家分享一个我们都关心的话题&mdash;&mdash;网站SEO快速排名算法对网站我们身处一个信息爆炸的时代,如何在海量的信息中脱颖而出,成为了一个我们不得...【详细内容】
2024-03-28  Search: 算法  点击:(12)  评论:(0)  加入收藏
当prompt策略遇上分治算法,南加大、微软让大模型炼成「火眼金睛」
近年来,大语言模型(LLMs)由于其通用的问题处理能力而引起了大量的关注。现有研究表明,适当的提示设计(prompt enginerring),例如思维链(Chain-of-Thoughts),可以解锁 LLM 在不同领域的...【详细内容】
2024-03-12  Search: 算法  点击:(12)  评论:(0)  加入收藏
谷歌宣布更新搜索算法:打击AI生成内容,提高搜索结果质量
IT之家 3 月 6 日消息,谷歌于当地时间 5 日发文宣布,针对用户对搜索结果质量下降的反馈,将对算法进行调整,旨在打击 AI 生成的内容以及内容农场等垃圾信息,使用户能够看到更多“...【详细内容】
2024-03-06  Search: 算法  点击:(38)  评论:(0)  加入收藏
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  Search: 算法  点击:(13)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03  Search: 算法  点击:(50)  评论:(0)  加入收藏
简易百科之什么是搜索引擎的PageRank算法?
简易百科之什么是搜索引擎的PageRank算法?在互联网时代,搜索引擎是我们获取信息的重要工具。而PageRank算法则是搜索引擎的核心技术之一,它决定了网页在搜索结果中的排名。那么...【详细内容】
2024-01-24  Search: 算法  点击:(50)  评论:(0)  加入收藏
PageRank算法揭秘:搜索引擎背后的魔法师的工作原理
PageRank(PR)算法是由谷歌创始人之一的拉里&middot;佩奇LarryPage命名的一种衡量网站页面重要性的方法。根据谷歌的说法,PageRank通过计算页面链接的数量和质量来粗略估计分...【详细内容】
2024-01-23  Search: 算法  点击:(44)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  Search: 算法  点击:(44)  评论:(0)  加入收藏
百度最新的搜索引擎算法是什么样的?
百度搜索引擎算法是百度用来决定网页排名的算法。它是百度搜索技术的核心,也是百度作为全球最大的中文搜索引擎的基石。随着互联网的发展和用户需求的不断变化,百度搜索引擎算...【详细内容】
2024-01-10  Search: 算法  点击:(86)  评论:(0)  加入收藏
▌简易百科推荐
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  二手车小胖说    Tags:流量算法   点击:(13)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03   一安未来  微信公众号  Tags:雪花算法   点击:(50)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  架构师老卢  今日头条  Tags:算法   点击:(44)  评论:(0)  加入收藏
百度推荐排序技术的思考与实践
本文将分享百度在推荐排序方面的思考与实践。在整个工业界的推广搜场景上,特征设计通常都是采用离散化的设计,需要保证两方面的效果,一方面是记忆,另一方面是泛化。特征都是通过...【详细内容】
2024-01-09  DataFunTalk  微信公众号  Tags:百度推荐   点击:(77)  评论:(0)  加入收藏
什么是布隆过滤器?如何实现布隆过滤器?
以下我们介绍了什么是布隆过滤器?它的使用场景和执行流程,以及在 Redis 中它的使用,那么问题来了,在日常开发中,也就是在 Java 开发中,我们又将如何操作布隆过滤器呢?布隆过滤器(Blo...【详细内容】
2024-01-05  Java中文社群  微信公众号  Tags:布隆过滤器   点击:(87)  评论:(0)  加入收藏
面向推荐系统的深度强化学习算法研究与应用
随着互联网的快速发展,推荐系统在各个领域中扮演着重要的角色。传统的推荐算法在面对大规模、复杂的数据时存在一定的局限性。为了解决这一问题,深度强化学习算法应运而生。本...【详细内容】
2024-01-04  数码小风向    Tags:算法   点击:(96)  评论:(0)  加入收藏
非负矩阵分解算法:从非负数据中提取主题、特征等信息
非负矩阵分解算法(Non-negativeMatrixFactorization,简称NMF)是一种常用的数据分析和特征提取方法,主要用于从非负数据中提取主题、特征等有意义的信息。本文将介绍非负矩阵分解...【详细内容】
2024-01-02  毛晓峰    Tags:算法   点击:(63)  评论:(0)  加入收藏
再谈前端算法,你这回明白了吗?
楔子 -- 青蛙跳台阶一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,求该青蛙跳上一个n级的台阶总共需要多少种跳法。分析: 当n=1的时候,①只需要跳一次即可;只有一种跳法,即f(...【详细内容】
2023-12-28  前端爱好者  微信公众号  Tags:前端算法   点击:(108)  评论:(0)  加入收藏
三分钟学习二分查找
二分查找是一种在有序数组中查找元素的算法,通过不断将搜索区域分成两半来实现。你可能在日常生活中已经不知不觉地使用了大脑里的二分查找。最常见的例子是在字典中查找一个...【详细内容】
2023-12-22  小技术君  微信公众号  Tags:二分查找   点击:(78)  评论:(0)  加入收藏
强化学习算法在资源调度与优化中的应用
随着云计算和大数据技术的快速发展,资源调度与优化成为了现代计算系统中的重要问题。传统的资源调度算法往往基于静态规则或启发式方法,无法适应动态变化的环境和复杂的任务需...【详细内容】
2023-12-14  职场小达人欢晓    Tags:算法   点击:(165)  评论:(0)  加入收藏
站内最新
站内热门
站内头条