负载均衡算法

简介: 本文介绍了多种负载均衡算法:随机、轮询、最小活跃数、源地址哈希及一致性哈希。涵盖适用场景、实现原理与代码示例,帮助理解如何高效分配请求,提升系统稳定性与性能。

随机

调用关系如上图(简化了公网->防火墙处理),适合场景:所有服务器性能基本一致,且无超阈值流量。

private K doSelect(List<K> nodes, String ip) {
    // 在列表中随机选取一个节点
    int index = random.nextInt(nodes.size());
    return nodes.get(index);
}

如果存在部分机器性能更优,此时可以在随机基础上增加权重,升级为:随机权重算法。

private K doSelect(List<K> nodes, String ip) {
    int length = nodes.size();
    AtomicInteger totalWeight = new AtomicInteger(0);
    for (K node : nodes) {
        Integer weight = node.getWeight();
        totalWeight.getAndAdd(weight);
    }
    if (totalWeight.get() > 0) {
        int offset = random.nextInt(totalWeight.get());
        for (N node : nodes) {
            // 让随机值 offset 减去当前node权重值
            offset -= node.getWeight();
            if (offset < 0) {
                // 当前node大于随机值offset,返回此Node
                return node;
            }
        }
    }
    // 随机返回
    return nodes.get(random.nextInt(length));
}

轮询

轮询不再是在多台服务器随机挑选,而是按照顺序一个个排队调用,调用完再插入队尾等待下一次调用

protected K doSelect(List<K> nodes, String ip) {
    int length = nodes.size();
    // 如果位置值已经等于长度重置为0(走一轮了)
    position.compareAndSet(length, 0);
    N node = nodes.get(position.get());
    // 数据原子增加,对应调用从1->2->3->4
    position.getAndIncrement();
    return node;
}

同加权随机,轮询也同样存在加权轮询的场景,此时流量调度将发生如下变化:

此处逻辑相对复杂,笔者在此说出主要思路,后续有时间补充伪代码,感兴趣的可以参照Dubbo的实现

如上有服务器servers=[A,B],对应权重weights=[3,1],总权重为4。我们可以理解为有4台服务器,3台A,1台B,一次调用过来的时候,需要按顺序访问。如有5次调用,调用顺序为AAABA。

选举思路如下:

次数

WeightedRoundRobin

选择结果

选择后的WeightedRoundRobin

1

3、1

A

2、1

2

2、1

A

1、1

3

1、1

A

0、1

4

0、1

B

0、0(等于0-0时复原成:3、1)

5

3、1

A

2、1

最小活跃数

指:将当前请求转发到连接数/请求数最少的机器上,其特点是根据服务器实时运行状态动态分配,保障服务负载不会过饱和。如下图当请求4过来时,Nginx判断目前服务器1连接数>服务器2,故4会请求到服务器2上:

源地址哈希

根据请求源IP哈希计算得到一个数值,用该数值在候选服务器列表的进行取模运算,得到的结果便是选中的服务器,此操作可以保证固定IP的请求总是到某一台服务器上,伪代码如下:

private K doSelect(List<K> nodes, String ip) {
    int length = nodes.size();
    int index = hash(ip) % length;
    return nodes.get(index);
}

一致性哈希

相同的请求尽可能落到同一个服务器上。一致性哈希解决稳定性问题,可以将所有的存储节点排列在首尾相接的 Hash 环上,每个 key 在计算 Hash 后会 顺时针找到临接的存储节点存放。而当有节点加入或退出时,仅影响该节点在 Hash环上顺时针相邻的后续节点。

相关文章
|
11月前
|
人工智能 监控 Java
请求限流
本文介绍如何使用Sentinel实现接口限流与降级,通过配置QPS阈值保护商品查询接口,并结合JMeter进行压测验证。同时讲解了线程隔离机制,包括信号量隔离的应用,确保系统在高并发下的稳定性。
请求限流
|
6月前
|
运维 监控 网络协议
排障本身不慢,MTTR却一直降不下来?时间都耗在这三个流程断点上
本文剖析MTTR居高不下的三大非技术断点:信息传递失真、工单推进停滞、跨部门信号断档。指出问题本质是流程链路断裂,而非排障能力不足,并给出低成本、可落地的三步改进方案:加推进超时提醒、标准化服务台字段、打通业务上报与端到端探测。(239字)
664 1
排障本身不慢,MTTR却一直降不下来?时间都耗在这三个流程断点上
|
5月前
|
SQL Oracle 关系型数据库
PL/SQL Developer 13.0.2 安装教程(Windows 64位 plsqldev1302x64.msi 详细步骤)
PL/SQL Developer 13.0.2 x64 是专为Oracle数据库设计的高效IDE,支持PL/SQL调试、SQL开发与对象管理。本教程详解64位Windows下安装步骤(含管理员运行、路径设置、桌面图标创建)及首次启动必备的Oracle Instant Client配置,助你快速上手。
|
11月前
|
项目管理 开发者
业务架构图
本文系统阐述了业务架构图的核心概念与绘制方法,涵盖业务定义、架构分层(组织层、应用层、能力层、基础层)、模块划分及功能分解,并结合医院场景示例,说明如何通过分层、分模块、分功能构建清晰的业务视图,提升客户理解与开发效率。
|
9月前
|
存储 人工智能 测试技术
从 Gemini 看 AI 系统设计的新趋势:上下文正在成为基础设施
本文探讨AI应用演进的关键转折:上下文正从临时输入升维为系统级资产。随着AI从“调用模型”转向“运行系统”,上下文的持久化、迁移性、版本化与解耦能力,已成为决定长期可用性的核心基础设施,远超模型参数本身。
|
10月前
|
JSON API 网络架构
什么是API?API有哪些类型?
本文深入浅出地讲解API的概念、类型及应用。API即应用程序接口,是软件间通信的桥梁。文章从开放、内部、合作伙伴API等分类入手,解析REST、SOAP、GraphQL等技术类型,并探讨其在数据与功能调用中的作用,帮助读者全面理解现代数字服务的底层逻辑。
15113 10
|
11月前
|
监控 Java Sentinel
熔断降级
熔断降级是防止服务雪崩的核心机制,通过Sentinel实现。熔断由客户端断路器统计异常或慢请求比例,超阈值后拦截请求;降级则返回默认数据保障体验。结合使用可快速失败、避免级联故障。
|
11月前
|
消息中间件 存储 缓存
RabbitMQ工作模型
工作队列模型通过多个消费者共同消费一个队列中的消息,实现任务的并行处理。默认情况下,消息平均分配给消费者,可能导致处理能力不同的消费者负载不均。通过设置`prefetch=1`,可实现“能者多劳”,即处理速度快的消费者自动接收更多消息,提升整体效率。发布订阅模型则通过交换机(Exchange)将一条消息转发给多个队列,支持Fanout、Direct、Topic等类型交换机,实现广播或多条件路由消息,满足不同业务场景需求。
|
11月前
|
存储 缓存 负载均衡
Nacos注册中心
本文介绍Nacos的安装部署、服务注册与发现、权重控制、集群隔离及临时/持久实例等核心功能,涵盖从环境搭建到高级配置的完整实践,助力微服务架构高效管理。
 Nacos注册中心
|
11月前
|
消息中间件 Java 数据安全/隐私保护
RabbitMQ入门
RabbitMQ是基于Erlang开发的开源消息中间件,支持AMQP协议,实现应用间解耦与异步通信。其核心组件包括生产者、消费者、队列、交换机和虚拟主机,可通过Docker快速部署并结合SpringAMQP实现消息收发。