18.9.6 负载均衡算法与实现策略

1. 负载均衡基础概念

1.1 负载均衡原理

public class LoadBalancingPrinciple {
    
    /*
     * 负载均衡核心概念:
     * 
     * 1. 基本作用
     *    - 将请求分发到多个服务器
     *    - 提高系统吞吐量和可用性
     *    - 避免单点过载
     * 
     * 2. 实现层次
     *    - 硬件负载均衡 (F5, A10)
     *    - 软件负载均衡 (Nginx, HAProxy)
     *    - 应用层负载均衡 (Ribbon, Dubbo)
     * 
     * 3. 常见算法
     *    - 轮询 (Round Robin)
     *    - 加权轮询 (Weighted Round Robin)
     *    - 随机 (Random)
     *    - 最少连接 (Least Connections)
     *    - 一致性哈希 (Consistent Hash)
     */
    
    public void demonstrateLoadBalancing() {
        System.out.println("=== 负载均衡算法演示 ===");
        
        // 创建服务器列表
        java.util.List<Server> servers = createServerList();
        
        demonstrateRoundRobin(servers);
        demonstrateWeightedRoundRobin(servers);
        demonstrateRandom(servers);
        demonstrateLeastConnections(servers);
        demonstrateConsistentHash(servers);
    }
    
    private java.util.List<Server> createServerList() {
        java.util.List<Server> servers = new java.util.ArrayList<>();
        servers.add(new Server("server-1", "192.168.1.10", 8080, 100));
        servers.add(new Server("server-2", "192.168.1.11", 8080, 200));
        servers.add(new Server("server-3", "192.168.1.12", 8080, 150));
        return servers;
    }
    
    private void demonstrateRoundRobin(java.util.List<Server> servers) {
        System.out.println("--- 轮询算法演示 ---");
        
        RoundRobinLoadBalancer roundRobin = new RoundRobinLoadBalancer(servers);
        
        System.out.println("连续5次请求分发:");
        for (int i = 1; i <= 5; i++) {
            Server selected = roundRobin.select();
            System.out.println("  请求" + i + " -> " + selected.getName());
        }
        System.out.println("轮询: 平均分配,简单公平\n");
    }
    
    private void demonstrateWeightedRoundRobin(java.util.List<Server> servers) {
        System.out.println("--- 加权轮询算法演示 ---");
        
        WeightedRoundRobinLoadBalancer weightedRR = new WeightedRoundRobinLoadBalancer(servers);
        
        System.out.println("连续10次请求分发 (权重 1:2:1.5):");
        for (int i = 1; i <= 10; i++) {
            Server selected = weightedRR.select();
            System.out.println("  请求" + i + " -> " + selected.getName() + " (权重:" + selected.getWeight() + ")");
        }
        System.out.println("加权轮询: 按权重分配,性能差异化\n");
    }
    
    private void demonstrateRandom(java.util.List<Server> servers) {
        System.out.println("--- 随机算法演示 ---");
        
        RandomLoadBalancer random = new RandomLoadBalancer(servers);
        
        System.out.println("连续5次请求分发:");
        for (int i = 1; i <= 5; i++) {
            Server selected = random.select();
            System.out.println("  请求" + i + " -> " + selected.getName());
        }
        System.out.println("随机: 简单实现,长期均匀\n");
    }
    
    private void demonstrateLeastConnections(java.util.List<Server> servers) {
        System.out.println("--- 最少连接算法演示 ---");
        
        LeastConnectionsLoadBalancer leastConn = new LeastConnectionsLoadBalancer(servers);
        
        System.out.println("模拟连接变化:");
        for (int i = 1; i <= 5; i++) {
            Server selected = leastConn.select();
            selected.incrementConnections();
            System.out.println("  请求" + i + " -> " + selected.getName() + " (连接数:" + selected.getConnections() + ")");
        }
        System.out.println("最少连接: 动态负载感知\n");
    }
    
    private void demonstrateConsistentHash(java.util.List<Server> servers) {
        System.out.println("--- 一致性哈希算法演示 ---");
        
        ConsistentHashLoadBalancer consistentHash = new ConsistentHashLoadBalancer(servers);
        
        System.out.println("相同key的请求分发:");
        String[] keys = {"user:123", "user:456", "user:123", "user:789", "user:123"};
        for (int i = 0; i < keys.length; i++) {
            Server selected = consistentHash.select(keys[i]);
            System.out.println("  " + keys[i] + " -> " + selected.getName());
        }
        System.out.println("一致性哈希: 相同key固定路由\n");
    }
}

// 服务器类
class Server {
    private String name;
    private String host;
    private int port;
    private int weight;
    private int connections;
    private boolean healthy;
    
    public Server(String name, String host, int port, int weight) {
        this.name = name;
        this.host = host;
        this.port = port;
        this.weight = weight;
        this.connections = 0;
        this.healthy = true;
    }
    
    public String getName() { return name; }
    public String getHost() { return host; }
    public int getPort() { return port; }
    public int getWeight() { return weight; }
    public int getConnections() { return connections; }
    public boolean isHealthy() { return healthy; }
    
    public void incrementConnections() { this.connections++; }
    public void decrementConnections() { this.connections--; }
    public void setHealthy(boolean healthy) { this.healthy = healthy; }
}

// 轮询负载均衡器
class RoundRobinLoadBalancer {
    private java.util.List<Server> servers;
    private java.util.concurrent.atomic.AtomicInteger counter = new java.util.concurrent.atomic.AtomicInteger(0);
    
    public RoundRobinLoadBalancer(java.util.List<Server> servers) {
        this.servers = new java.util.ArrayList<>(servers);
    }
    
    public Server select() {
        if (servers.isEmpty()) {
            return null;
        }
        
        int index = counter.getAndIncrement() % servers.size();
        return servers.get(index);
    }
}

// 加权轮询负载均衡器
class WeightedRoundRobinLoadBalancer {
    private java.util.List<Server> servers;
    private java.util.List<WeightedServer> weightedServers;
    
    public WeightedRoundRobinLoadBalancer(java.util.List<Server> servers) {
        this.servers = servers;
        this.weightedServers = new java.util.ArrayList<>();
        
        for (Server server : servers) {
            weightedServers.add(new WeightedServer(server, server.getWeight(), 0));
        }
    }
    
    public Server select() {
        if (weightedServers.isEmpty()) {
            return null;
        }
        
        int totalWeight = weightedServers.stream().mapToInt(ws -> ws.getWeight()).sum();
        
        // 增加当前权重
        for (WeightedServer ws : weightedServers) {
            ws.setCurrentWeight(ws.getCurrentWeight() + ws.getWeight());
        }
        
        // 选择当前权重最大的服务器
        WeightedServer selected = weightedServers.stream()
            .max((ws1, ws2) -> Integer.compare(ws1.getCurrentWeight(), ws2.getCurrentWeight()))
            .orElse(null);
        
        if (selected != null) {
            selected.setCurrentWeight(selected.getCurrentWeight() - totalWeight);
            return selected.getServer();
        }
        
        return null;
    }
}

// 加权服务器
class WeightedServer {
    private Server server;
    private int weight;
    private int currentWeight;
    
    public WeightedServer(Server server, int weight, int currentWeight) {
        this.server = server;
        this.weight = weight;
        this.currentWeight = currentWeight;
    }
    
    public Server getServer() { return server; }
    public int getWeight() { return weight; }
    public int getCurrentWeight() { return currentWeight; }
    public void setCurrentWeight(int currentWeig

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务