常见的负载均衡策略

轮询(Round Robin)

轮询的实现方式比较简单,就是将请求以此分发到后端服务器中,将所有的请求均匀分配,均匀分配的坏处是通常后台服务器性能有差异,有时候希望性能较好的服务器可以多承担些请求,该策略无法满足需求。这个不适合对长连接和命中率有要求的场景。

加强轮询(Weighted Round Robin)

这种策略是对轮询策略的优化,对每个后端服务器设置一个权重值,根据权重值决定请求的分配比例,这种做法解决了轮询策略的不足,但是该权限值需要手动配置,没有办法自动动态调节,同样不适合对长连接和命中率有要求的场景。

hash算法

通过ip url等信息计算hash值,然后对服务器的数量取模,相同的请求会请求到同一个后端服务器中。该算法无法解决热点请求,会把某个时间段的热点请求路由到某个单机上,造成雪崩效应,同时在扩中和节点宕机时发生命中率急剧降低的问题(hash算法导致),该策略适合维护长连接和提高命中率。

随机Random

根据随机算法,将请求随机分配到后端服务器中,请求的均匀请求依赖于随机算法,该实现方式较为简单,常常可以配合处理一些极端的请求,例如热点请求情况。不适合对命中率有要求的场景。

一致性hash算法

对hash 算法的优化,可以有效的解决宕机和扩充造成的命中率急剧降低的问题。

最小连接数 Least Connection

通过活动来估计后端服务器的负载,把请求分配给活动连接数最小的后端服务器,算法比较智能,但是需要额外的资源维护后端服务器的连接列表。

加权最小连接数 Weighted Least Connection

对Least Connection策略的优化,通过加权的方式优化Least Connection的性能,对性能较好的后端服务器设置较高的权重,承担更多的链接负载。

最短响应时间 Least Response Time

该策略的意思就是将请求分配给平均响应时间最短的后端服务器,平均时间可以通过ping或者正常的响应时间来获取 。

 

可以总结为,轮巡、随机、权重、并发量

 

 

 


后面会逐一对各个常见的负载均衡策略的实现做介绍。

自我总结
在 Java 开发中,负载均衡是一种将工作负载分布到多个计算资源(如服务器、处理器等)上的技术,以提高系统的性能、可用性和可扩展性。以下是几种常见的 Java 负载均衡策略及示例说明。

1. 轮询策略(Round Robin)

原理

轮询策略是最简单的负载均衡策略之一。它按照顺序依次将请求分配到可用的服务器列表中的每一台服务器,当所有服务器都被分配过一次后,再从头开始循环。

示例代码

import java.util.ArrayList;
import java.util.List;

// 模拟服务器列表
class Server {
    private String name;

    public Server(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

// 轮询负载均衡器
class RoundRobinLoadBalancer {
    private List<Server> servers;
    private int currentIndex = 0;

    public RoundRobinLoadBalancer(List<Server> servers) {
        this.servers = servers;
    }

    public Server getNextServer() {
        Server server = servers.get(currentIndex);
        currentIndex = (currentIndex + 1) % servers.size();
        return server;
    }
}

public class RoundRobinExample {
    public static void main(String[] args) {
        List<Server> servers = new ArrayList<>();
        servers.add(new Server("Server1"));
        servers.add(new Server("Server2"));
        servers.add(new Server("Server3"));

        RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(servers);

        // 模拟 5 次请求
        for (int i = 0; i < 5; i++) {
            Server server = loadBalancer.getNextServer();
            System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
        }
    }
}

代码解释

在上述代码中,RoundRobinLoadBalancer 类实现了轮询负载均衡策略。getNextServer 方法会依次返回服务器列表中的服务器,当到达列表末尾时,会重新从列表头部开始。

2. 随机策略(Random)

原理

随机策略会随机选择一台可用的服务器来处理请求。这种策略简单且易于实现,但可能会导致服务器负载不均衡。

示例代码

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

// 模拟服务器列表
class Server {
    private String name;

    public Server(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

// 随机负载均衡器
class RandomLoadBalancer {
    private List<Server> servers;
    private Random random = new Random();

    public RandomLoadBalancer(List<Server> servers) {
        this.servers = servers;
    }

    public Server getNextServer() {
        int index = random.nextInt(servers.size());
        return servers.get(index);
    }
}

public class RandomExample {
    public static void main(String[] args) {
        List<Server> servers = new ArrayList<>();
        servers.add(new Server("Server1"));
        servers.add(new Server("Server2"));
        servers.add(new Server("Server3"));

        RandomLoadBalancer loadBalancer = new RandomLoadBalancer(servers);

        // 模拟 5 次请求
        for (int i = 0; i < 5; i++) {
            Server server = loadBalancer.getNextServer();
            System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
        }
    }
}

代码解释

RandomLoadBalancer 类实现了随机负载均衡策略。getNextServer 方法会随机选择一个服务器索引,并返回对应的服务器。

3. 加权轮询策略(Weighted Round Robin)

原理

加权轮询策略是轮询策略的改进版。为每台服务器分配一个权重,权重越高的服务器被分配到请求的概率越大。例如,服务器 A 的权重为 3,服务器 B 的权重为 1,那么在 4 次请求中,服务器 A 可能会被分配到 3 次,服务器 B 会被分配到 1 次。

示例代码

import java.util.ArrayList;
import java.util.List;

// 模拟服务器列表
class Server {
    private String name;
    private int weight;

    public Server(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public int getWeight() {
        return weight;
    }
}

// 加权轮询负载均衡器
class WeightedRoundRobinLoadBalancer {
    private List<Server> servers;
    private int currentIndex = 0;
    private int currentWeight = 0;
    private int gcd; // 最大公约数
    private int maxWeight; // 最大权重

    public WeightedRoundRobinLoadBalancer(List<Server> servers) {
        this.servers = servers;
        this.gcd = getGCD(servers);
        this.maxWeight = getMaxWeight(servers);
    }

    private int getGCD(List<Server> servers) {
        int gcd = servers.get(0).getWeight();
        for (int i = 1; i < servers.size(); i++) {
            gcd = gcd(gcd, servers.get(i).getWeight());
        }
        return gcd;
    }

    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    private int getMaxWeight(List<Server> servers) {
        int max = servers.get(0).getWeight();
        for (int i = 1; i < servers.size(); i++) {
            if (servers.get(i).getWeight() > max) {
                max = servers.get(i).getWeight();
            }
        }
        return max;
    }

    public Server getNextServer() {
        while (true) {
            currentIndex = (currentIndex + 1) % servers.size();
            if (currentIndex == 0) {
                currentWeight = currentWeight - gcd;
                if (currentWeight <= 0) {
                    currentWeight = maxWeight;
                    if (currentWeight == 0) {
                        return null;
                    }
                }
            }
            Server server = servers.get(currentIndex);
            if (server.getWeight() >= currentWeight) {
                return server;
            }
        }
    }
}

public class WeightedRoundRobinExample {
    public static void main(String[] args) {
        List<Server> servers = new ArrayList<>();
        servers.add(new Server("Server1", 3));
        servers.add(new Server("Server2", 1));
        servers.add(new Server("Server3", 2));

        WeightedRoundRobinLoadBalancer loadBalancer = new WeightedRoundRobinLoadBalancer(servers);

        // 模拟 6 次请求
        for (int i = 0; i < 6; i++) {
            Server server = loadBalancer.getNextServer();
            System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
        }
    }
}

代码解释

WeightedRoundRobinLoadBalancer 类实现了加权轮询负载均衡策略。通过计算服务器权重的最大公约数和最大权重,按照一定规则依次选择服务器。

4. 最少连接策略(Least Connections)

原理

最少连接策略会选择当前连接数最少的服务器来处理请求。这种策略可以使服务器的负载更加均衡,因为它会优先将请求分配给负载较轻的服务器。

示例代码(简单模拟)

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

// 模拟服务器列表
class Server {
    private String name;
    private int connections;

    public Server(String name) {
        this.name = name;
        this.connections = 0;
    }

    public String getName() {
        return name;
    }

    public int getConnections() {
        return connections;
    }

    public void incrementConnections() {
        connections++;
    }

    public void decrementConnections() {
        connections--;
    }
}

// 最少连接负载均衡器
class LeastConnectionsLoadBalancer {
    private List<Server> servers;

    public LeastConnectionsLoadBalancer(List<Server> servers) {
        this.servers = servers;
    }

    public Server getNextServer() {
        return servers.stream()
               .min(Comparator.comparingInt(Server::getConnections))
               .orElse(null);
    }
}

public class LeastConnectionsExample {
    public static void main(String[] args) {
        List<Server> servers = new ArrayList<>();
        servers.add(new Server("Server1"));
        servers.add(new Server("Server2"));
        servers.add(new Server("Server3"));

        LeastConnectionsLoadBalancer loadBalancer = new LeastConnectionsLoadBalancer(servers);

        // 模拟 5 次请求
        for (int i = 0; i < 5; i++) {
            Server server = loadBalancer.getNextServer();
            server.incrementConnections();
            System.out.println("Request " + (i + 1) + " is sent to " + server.getName());
        }
    }
}

代码解释

LeastConnectionsLoadBalancer 类实现了最少连接负载均衡策略。getNextServer 方法会选择当前连接数最少的服务器。每次请求分配后,会增加对应服务器的连接数。

这些负载均衡策略各有优缺点,在实际应用中,需要根据具体的业务场景和服务器配置选择合适的策略。

posted @   皇问天  阅读(540)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2017-04-24 java面试题总结
2017-04-24 Spring 使用注解方式进行事务管理
2017-04-24 高级程序员的面试题整理
2017-04-24 Web性能优化
2017-04-24 设计模式-单例模式7种写法
2017-04-24 线程池的原理及实现
点击右上角即可分享
微信分享提示