JAVA常用负载均衡算法实现

如何用Netty实现一个负载均衡组件 码农设计 阅读详情

一、负载均衡的概念



      在大型的分布式架构中,对于负载较高的服务来说,往往对应着多台机器组成的集群,当请求到来的时候,为了将请求均衡的分配给后端服务器需要有相应的负载均衡算法来支持,通过相应的负载均衡算法选取一台机器来处理客户端请求,这个过程称为服务的负载均衡。


二、常用负载均衡算法实现


       常用的负载均衡算法主要有随机法,轮询法,加权随机,加权轮询,最小连接数,一致性hash等。随机法,轮询法都比较简单,随机算法不考虑服务器的负载实际中很少使用,轮询算法在服务的上线下线时无法及时感应到也较少使用,下面重点介绍比较常用的加权轮询和一致性hash。 

 2.1 负载均衡接口
 
import java.util.List;
 
import cn.fzjh.vo.ServiceInstance;
 
public interface LoadBalance {
     
    //根据请求选择一个服务实例
    ServiceInstance chooseServerInstance();
 
    /**
     * 设置服务的信息
     * 
     * @param serviceName 服务名
     * @param version 服务版本
     */
    void setService(String serviceName, String version);
     
    /**
     * 初始化
     */
    void init();
     
    /**
     * 获取全部服务列表
     * 
     * @return
     */
    List<serviceinstance> getServiceInstanceList();
     
    /**
     * 更新服务实例列表
     */
    void updateServerInstanceList();
     
    /**
     * 隔离一个服务实例
     * 
     * @param server
     */
    void isolateServerInstance(String server);
 
    /**
     * 恢复一个服务实例
     * 
     * @param server
     */
    void resumeServerInstance(String server);
}

    2.2 抽象负载均衡基类

   

import java.util.List;
import java.util.Random;
 
import javax.annotation.Resource;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import cn.fzjh.jk.LoadBalance;
import cn.fzjh.rule.DynamicUploadRule;
import cn.fzjh.vo.ServiceInstance;
 
//抽象的负载均衡基类,提供基本的服务信息和相关服务实例列表的管理
public abstract class AbstractLoadBalance implements LoadBalance {
 
    protected final Logger logger = LoggerFactory
            .getLogger(AbstractLoadBalance.class);
     
    @Resource(name="dynamicUploadRule")
    private transient DynamicUploadRule dynamicUploadRule;
 
    protected String serviceName;
 
    protected String version;
 
    // 特定版本的服务的标识
    private transient String serviceKey;
 
    protected List<serviceinstance> serviceInstanceList;
 
    @Override
    public void setService(String serviceName, String version) {
        this.serviceName = serviceName;
        this.version = version;
        this.serviceKey = genKey(serviceName, version);
    }
 
    // 随机算法获取可利用的服务列表
    @Override
    public ServiceInstance chooseServerInstance() {
        List<serviceinstance> allServiceList = getAllServiceInstanceList();
        if (null == allServiceList) {
            return null;
        }
        ServiceInstance serviceInstance = null;
        int indexOfLoop = 0;
        Random random = new Random();
        if (null != allServiceList && allServiceList.size() > 0) {
            int serviceCount = allServiceList.size();
            while (null == serviceInstance && indexOfLoop < serviceCount * 5) {// 由于是随机选取,不能在serverCount内选出
                int index = random.nextInt(serviceCount);
                serviceInstance = allServiceList.get(index);
                logger.info("随机选择算法获取可用的服务:" + serviceInstance.getServerName());
                if (serviceInstance.isIsolated()) {
                    logger.info("选择的服务暂时不可用:" + serviceInstance.getServerName()
                            + ",重新选择");
                    indexOfLoop++;
                    serviceInstance = null;
                }
            }
        }
        return serviceInstance;
    }
 
    @Override
    public void init() {
        // 拿到所有的服务器列表
        List<serviceinstance> serviceInstances = getAllServiceInstanceList();
        setServiceInstanceList(serviceInstances);
    }
 
    @Override
    public List<serviceinstance> getServiceInstanceList() {
        return serviceInstanceList;
    }
 
    @Override
    public void updateServerInstanceList() {
        // 这里实际上应该重新获取注册的服务信息更新,此处默认
        List<serviceinstance> serviceInstanceList = getAllServiceInstanceList();
        setServiceInstanceList(serviceInstanceList);
    }
 
    @Override
    public void isolateServerInstance(String serverName) {
        for (final ServiceInstance serverInstance : serviceInstanceList) {
            if (serverName.equals(serverInstance.getServerName())) {
                serverInstance.setIsolated(true);
                break;
            }
        }
    }
 
    @Override
    public void resumeServerInstance(String serverName) {
        for (final ServiceInstance serverInstance : serviceInstanceList) {
            if (serverName.equals(serverInstance.getServerName())) {
                serverInstance.setIsolated(false);
                break;
            }
        }
    }
 
    //通过服务名获取服务实例
    protected ServiceInstance getServiceInstanceByServiceName(String serviceName) {
        ServiceInstance serviceInstance = null;
        List<serviceinstance> serviceInstances = getAllServiceInstanceList();
        if (null == serviceInstances) {
            return null;
        }
        for (final ServiceInstance instance : serviceInstances) {
            if (instance.getServerName().equals(serviceName)) {
                serviceInstance = instance;
                break;
            }
        }
        return serviceInstance;
    }
 
    private String genKey(String serviceName, String version) {
        return new StringBuffer().append(serviceName).append('#')
                .append(version).toString();
    }
 
    private List<serviceinstance> getAllServiceInstanceList() {
        // 模拟服务器注册后的服务实例
        List<serviceinstance> serviceInstanceList = dynamicUploadRule.getServiceInstanceRule();
        return serviceInstanceList;
    }
     
    protected String getServiceNameByServiceKey(String serviceKey){
        int index = serviceKey.indexOf('#');
        return serviceKey.substring(0, index);
    }
 
    public String getServiceName() {
        return serviceName;
    }
 
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }
 
    public String getVersion() {
        return version;
    }
 
    public void setVersion(String version) {
        this.version = version;
    }
 
    public String getServiceKey() {
        return serviceKey;
    }
 
    public void setServiceKey(String serviceKey) {
        this.serviceKey = serviceKey;
    }
 
    public void setServiceInstanceList(List<serviceinstance> serviceInstanceList) {
        this.serviceInstanceList = serviceInstanceList;
    }

   2.3 一致性hash算法

      目前在企业里面常用的基于内存的缓存服务memcached默认采用的负载均衡算法就是一致性hash算法,一致性hash算法可用保证对同一参数的请求将会是同一个服务器来处理,其原理大概如下:我们可以将可利用的服务器列表映射到一个hash环上,当客户端请求过来时,求出key的hash值映射到hash环上,然后顺时针查找,找到的第一台机器就是出来该请求的服务,如果循环完了还是没找到,那么就将请求转给hash环上的第一台机器处理,可以想象的是,如果咱们的集群足够大,可能循环很久才能找到对应的服务器,这就加大了网络IO

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
 
import cn.fzjh.abstrac.AbstractLoadBalance;
import cn.fzjh.consistenthash.ConsistentHash;
import cn.fzjh.consistenthash.MurmurHash3;
import cn.fzjh.vo.ServiceInstance;
 
@Service("consistentHashLoadBalance")
//基于一致性hash算法实现负载均衡
public class ConsistentHashLoadBalance extends AbstractLoadBalance {
 
    private static final Logger logger = LoggerFactory
            .getLogger(ConsistentHashLoadBalance.class);
 
    // 虚拟节点总数,用来计算各个服务器的虚拟节点总数
    public static final int VITRUAL_NODE_NUMBER = 1000;
 
    // 默认的每个服务器的虚拟节点个数
    public static final int DEFALUT_NODE_NUMBER = 30;
 
        //原子更新引用
    private AtomicReference<consistenthash<serviceinstance>> hashRing = new AtomicReference<consistenthash<serviceinstance>>();
 
    //虚拟节点个数,初始化时根据服务节点数计算,不随服务节点变化而变化
    private int numberOfReplicas;
     
    public ServiceInstance chooseServerInstance(String serviceKey) {
        this.serviceName = getServiceNameByServiceKey(serviceKey);
        //从哈希环中找到对应的节点以及后续的节点
        List<serviceinstance> instances = hashRing.get().getNUniqueBinsFor(serviceName, getServiceInstanceList().size());
        ServiceInstance serviceInstance = null;
        //循环每个阶段,直至找出没有被隔离的服务器
        for(ServiceInstance instance: instances){
            if(instance.isIsolated()){
                logger.info("服务被隔离了,暂时不可用:" + serviceName);
            } else {
                //顺时针找到第一个后就返回
                serviceInstance = instance;
                break;
            }
        }
        return serviceInstance;
    }
 
    @Override
    public void init() {
        super.init();
        numberOfReplicas = getServiceInstanceList().isEmpty()?DEFALUT_NODE_NUMBER:VITRUAL_NODE_NUMBER/getServiceInstanceList().size();
        buildHashLoop();
    }
 
    private void buildHashLoop() {
        logger.info("开始构建hash环");
        hashRing.set(new ConsistentHash<serviceinstance>(MurmurHash3.getInstance(),numberOfReplicas,serviceInstanceList));
    }
 
}

    一致性hash测试类:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import cn.fzjh.loadBalance.rule.ConsistentHashLoadBalance;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class TestConsistentHashLoadBalance {
     
    @Autowired
    private transient ConsistentHashLoadBalance consistentHashLoadBalance;
     
     
    @Test
    public void testConsistentLoadBalance() throws InterruptedException{
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(15, 20, 60,
                TimeUnit.SECONDS, new ArrayBlockingQueue<runnable>(3));
        for(int i=1;i<=15;i++){
            final int index = i;
            poolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("当前线程: " + Thread.currentThread().getName() + ",serviceKey:" + "127.0.0." + index  + ",选择服务:" + consistentHashLoadBalance.chooseServerInstance("127.0.0." + index + "#1.0.0" ).getServerName());
                }
            });
        }
    }
 
}
 
////////////////////////////////////多跑几次效果如下////////////////////////////////////////////
 
当前线程: pool-1-thread-2,serviceKey:127.0.0.2,选择服务:127.0.0.2
当前线程: pool-1-thread-5,serviceKey:127.0.0.5,选择服务:127.0.0.3
当前线程: pool-1-thread-10,serviceKey:127.0.0.10,选择服务:127.0.0.1
当前线程: pool-1-thread-9,serviceKey:127.0.0.9,选择服务:127.0.0.3
当前线程: pool-1-thread-3,serviceKey:127.0.0.3,选择服务:127.0.0.1
当前线程: pool-1-thread-4,serviceKey:127.0.0.4,选择服务:127.0.0.2
当前线程: pool-1-thread-1,serviceKey:127.0.0.1,选择服务:127.0.0.1
当前线程: pool-1-thread-14,serviceKey:127.0.0.14,选择服务:127.0.0.1
当前线程: pool-1-thread-6,serviceKey:127.0.0.6,选择服务:127.0.0.1
当前线程: pool-1-thread-13,serviceKey:127.0.0.13,选择服务:127.0.0.2
当前线程: pool-1-thread-7,serviceKey:127.0.0.7,选择服务:127.0.0.2
当前线程: pool-1-thread-8,serviceKey:127.0.0.8,选择服务:127.0.0.2
当前线程: pool-1-thread-11,serviceKey:127.0.0.11,选择服务:127.0.0.2
当前线程: pool-1-thread-15,serviceKey:127.0.0.15,选择服务:127.0.0.1
当前线程: pool-1-thread-12,serviceKey:127.0.0.12,选择服务:127.0.0.1
 
//////////////////////////////////////////////////////////////////
 
当前线程: pool-1-thread-1,serviceKey:127.0.0.1,选择服务:127.0.0.1
当前线程: pool-1-thread-2,serviceKey:127.0.0.2,选择服务:127.0.0.2
当前线程: pool-1-thread-10,serviceKey:127.0.0.10,选择服务:127.0.0.1
当前线程: pool-1-thread-5,serviceKey:127.0.0.5,选择服务:127.0.0.3
当前线程: pool-1-thread-14,serviceKey:127.0.0.14,选择服务:127.0.0.1
当前线程: pool-1-thread-6,serviceKey:127.0.0.6,选择服务:127.0.0.1
当前线程: pool-1-thread-3,serviceKey:127.0.0.3,选择服务:127.0.0.1
当前线程: pool-1-thread-7,serviceKey:127.0.0.7,选择服务:127.0.0.2
当前线程: pool-1-thread-11,serviceKey:127.0.0.11,选择服务:127.0.0.2
当前线程: pool-1-thread-15,serviceKey:127.0.0.15,选择服务:127.0.0.1
当前线程: pool-1-thread-9,serviceKey:127.0.0.9,选择服务:127.0.0.3
当前线程: pool-1-thread-13,serviceKey:127.0.0.13,选择服务:127.0.0.2
当前线程: pool-1-thread-4,serviceKey:127.0.0.4,选择服务:127.0.0.2
当前线程: pool-1-thread-8,serviceKey:127.0.0.8,选择服务:127.0.0.2
当前线程: pool-1-thread-12,serviceKey:127.0.0.12,选择服务:127.0.0.1

    可以看到,同一个请求经过hash后找到的处理请求的服务器是同一台

  2.4 加权轮询

    对一些性能高,负载低的服务器,我们可以给它更高的权值,以便处理更多的请求

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
 
import javax.annotation.Resource;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
 
import cn.fzjh.abstrac.AbstractLoadBalance;
import cn.fzjh.rule.DynamicUploadRule;
import cn.fzjh.vo.ServiceInstance;
 
//按照服务器权重的赋值均衡算法
@Service("weightedRoundRoBinLoadBalance")
public final class WeightedRoundRoBinLoadBalance extends AbstractLoadBalance {
 
    protected final Logger logger = LoggerFactory
            .getLogger(WeightedRoundRoBinLoadBalance.class);
     
    @Resource(name="dynamicUploadRule")
    private transient DynamicUploadRule dynamicUploadRule;
 
    // 所有服务器负载因子的最大公约数
    private int gcd;
 
    // 负载因子的最大值
    private int max;
 
    // 轮询周期
    private int cycle;
 
    // 当前使用的轮询的索引值
    private int currentIndex = -1;
     
    /**
     * 一个轮询周期的服务集合,长度为负载因子除以最大公约数相加确定,可重复,AtomicReference保证原子操作
     */
    private AtomicReference<list<string>> WRRList = new AtomicReference<list<string>>();
 
    @Override
    public void init() {
        super.init();
        buildWRRList();
    }
 
    @Override
    public ServiceInstance chooseServerInstance() {
        if (!isNotEmpty(WRRList.get())) {
            logger.info("还未建立起权值轮询服务集合,采用随机算法返回可利用的服务");
            return super.chooseServerInstance();
        }
        ServiceInstance serviceInstance = null;
        synchronized (this) {
            int index = 0;
            while (index < cycle && null == serviceInstance) {
                currentIndex = (currentIndex + 1) % WRRList.get().size();
                String serviceName = WRRList.get().get(currentIndex);
                serviceInstance = getServiceInstanceByServiceName(serviceName);
                if (null == serviceInstance || serviceInstance.isIsolated()) {
                    index++;
                }
            }
        }
        return serviceInstance;
    }
 
    /**
    * 初始化可利用的轮询周期内的服务集合
    */
    private void buildWRRList() {
        boolean isGetSucc = false;
        if (!getServiceInstanceList().isEmpty()) {
            logger.info("获取的服务列表不为空,开始初始化各个服务器对应的负载因子");
            isGetSucc = calcLoadFactors();
        }
        if (isGetSucc) {
            // 生成轮询的server集合
            int total = getServiceInstanceList().size();
            // 上一次服务库索引
            int i = -1;
            // 上一次权值
            int cw = 0;
            List<string> newWrrList = new ArrayList<string>(total);
            // 下面的算法,第一次分配时,把当前权重设置为最大权重,服务器中权重大于等于当前权重的,都会分配负载;
            // 第一轮分配完后,当前权重减最大公约数,进行第二轮分配;
            // 如此循环到当前权重为负,则把当前权重重置为最大权重,重新进行循环。一直到轮回周期
            for (int j = 0; j < cycle; j++) {
                while (true) {
                    i = (i + 1) % total;// 服务器下标
                    if (i == 0) {
                        cw = cw - gcd;// 获得处理的权重
                        if (cw <= 0) {
                            cw = max;
                            // 如果没有需要分配的服务
                            if (cw == 0) {
                                newWrrList.add(null);
                                break;
                            }
                        }
                    }
                    ServiceInstance serviceInstance = getServiceInstanceList()
                            .get(i);
                    String serverName = serviceInstance.getServerName();
                    // 如果被轮询到的server权值满足要求记录servername.
                    if(serviceInstance.getQzValue() >= cw){
                        newWrrList.add(serverName);
                        break;
                    }
                }
            }
            WRRList.set(newWrrList);
        }
    }
 
    /**
     * 初始化最大公约数,最大权值,轮询周期
     * @return
     */
    private boolean calcLoadFactors() {
        // 获取所有服务器列表,根据列表返回一开始设置的各服务器负载因子(这里可以是动态文件,可以是查询DB等方式)
        /**
         * 1:获取所有的服务名 2:根据服务名获取不同的服务设置的负载因子
         */
        // 获取所有服务的负载因子
        List<integer> factors = getDefault();
        if (null == factors || factors.size() == 0) {
            return false;
        }
        // 计算最大公约数 eg:10,20的最大公约数是10
        gcd = calcMaxGCD(factors);
        max = calcMaxValue(factors);
        cycle = calcCycle(factors, gcd);
        return true;
    }
 
    /**
     * 计算轮回周期,每个因子/最大公约数之后相加
     * eg:100/100 + 200/100 + 300/100 = 6
     * @param factors 存储所有的负载因子
     * @param gcd 最大公约数
     * @return
     */
    private int calcCycle(List<integer> factors, int gcd) {
        int cycle = 0;
        for (int i = 0; i < factors.size(); i++) {
            cycle += factors.get(i) / gcd;
        }
        return cycle;
    }
 
    /**
     * 计算负载因子最大值
     * 
     * @param factors
     * @return
     */
    private int calcMaxValue(List<integer> factors) {
        int max = 0;
        for (int i = 0; i < factors.size(); i++) {
            if (factors.get(i) > max) {
                max = factors.get(i);
            }
        }
        return max;
    }
 
    /**
     * 计算最大公约数
     * @param factors
     * @return
     */
    private int calcMaxGCD(List<integer> factors) {
        int max = 0;
        for (int i = 0; i < factors.size(); i++) {
            if (factors.get(i) > 0) {
                max = divisor(factors.get(i), max);
            }
        }
        return max;
    }
 
    /**
     * 使用辗转相减法计算
     * @param m 第一次参数
     * @param n 第二个参数
     * @return int最大公约数
     */
    private int divisor(int m, int n) {
        if (m < n) {
            int temp;
            temp = m;
            m = n;
            n = temp;
        }
        if (0 == n) {
            return m;
        }
        return divisor(m - n, n);
    }
 
    /**
     * 获取默认的负载因子
     * @param serviceNames 服务名
     * @return
     */
    private List<integer> getDefault() {
        List<integer> list = new ArrayList<integer>();
        List<serviceinstance> instances = dynamicUploadRule.getServiceInstanceRule();
        for (final ServiceInstance serviceInstance : instances) {
           list.add(serviceInstance.getQzValue());
         }
        return list;
    }
 
    /**
     * 判断非空
     * @param list
     * @return
     */
    private boolean isNotEmpty(List<string> list) {
        return null != list && list.size() > 0;
    }
 
}

   加权轮询测试类

 

 
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import cn.fzjh.loadBalance.rule.WeightedRoundRoBinLoadBalance;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class TestWeightRoundRoBinLoadBalance {
     
    @Autowired
    private transient WeightedRoundRoBinLoadBalance weightedRoundRoBinLoadBalance;
     
     
    @Test
    public void testWeightedRoundRoBinLoadBalance(){
        ExecutorService executorService = Executors.newFixedThreadPool(18);
        for(int i=1;i<=18;i++){
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("当前线程: " + Thread.currentThread().getName() + "选择服务:" + weightedRoundRoBinLoadBalance.chooseServerInstance().getServerName());
                }
            });
        }
    }
 
}
///////////////////////////////////////效果/////////////////////////////////////////
当前线程: pool-1-thread-1选择服务:127.0.0.2
当前线程: pool-1-thread-2选择服务:127.0.0.2
当前线程: pool-1-thread-3选择服务:127.0.0.3
当前线程: pool-1-thread-4选择服务:127.0.0.1
当前线程: pool-1-thread-5选择服务:127.0.0.2
当前线程: pool-1-thread-6选择服务:127.0.0.3
当前线程: pool-1-thread-7选择服务:127.0.0.2
当前线程: pool-1-thread-8选择服务:127.0.0.2
当前线程: pool-1-thread-9选择服务:127.0.0.3
当前线程: pool-1-thread-10选择服务:127.0.0.1
当前线程: pool-1-thread-12选择服务:127.0.0.2
当前线程: pool-1-thread-14选择服务:127.0.0.3
当前线程: pool-1-thread-16选择服务:127.0.0.2
当前线程: pool-1-thread-13选择服务:127.0.0.2
当前线程: pool-1-thread-18选择服务:127.0.0.3
当前线程: pool-1-thread-17选择服务:127.0.0.1
当前线程: pool-1-thread-11选择服务:127.0.0.2
当前线程: pool-1-thread-15选择服务:127.0.0.3

     考虑不完善的地方欢迎大家多交流,共同学习进步!

 

三端口DC-DC变换器设计与光伏储能协同控制 三端口DC-DC变换器是面向分布式能源系统的关键功率变换拓扑,通过在光伏输入、储能电池与直流负载三个端口间实现动态能量分配,解决多源异步供电下的电压稳定与功率平衡问题。其核心原理基于双Boost半桥架构与双闭环协同控制,融合MPPT最大功率点跟踪与电池智能充放电管理,在保证30V高精度稳压(±0.5V)的同时,支持光伏主导供电与电池支撑供电的自动模式切换。该技术显著提升光储系统能量利用率与供电连续性,广泛应用于微电网、便携式交直流电源及离网型光储一体机等场景,是构建柔性直流配电与智能能源管理的基础硬件单元。 阅读详情

相关推荐

计算机视觉之ResNet

RestNet是2015年由微软团队提出的,在当时获得分类任务,目标检测,图像分割第一名。该论文的四位作者何恺明、张祥雨、任少卿和孙剑如今在人工智能领域里都是响当当的名字,当时他们都是微软亚研的一员。实验结果显示,残差网络更容易优化,并且加深网络层数有助于提高正确率。在ImageNet上使用152层的残差网络(VGG net的8倍深度,但残差网络复杂度更低)。对这些网络使用集成方法实现了3.75%的错误率。获得了ILSVRC 2015竞赛的第一名。原文链接这是一篇计算机视觉领域的经典论文。

十年以上架构设计经验,专注于软件架构和人工智能领域,对机器视觉、NLP、音视频等领域都有涉猎 2万+

负载均衡算法详解及Java代码演示

在分布式系统中,负载均衡是确保各个服务器能够高效处理请求的重要组成部分。负载均衡算法根据不同的策略和需求,可以分为静态负载均衡和动态负载均衡,以及基于权重和基于性能的负载均衡。

nbsaas-boot基于Request-Response的企业级快速开发框架 1059

公文派2025:免费社区版重大安装更新!

距离上一次更新已经过去了将近一年的时间,今天我们带来了全新的免费2025社区版,该版本也是目前最新的版本,无需授权即可使用所有的功能。

似最初 1963

esl:uniqid=uuid

修改internal.xml中 inbound-use-callid-as-uuid <param name="inbound-use-callid-as-uuid" value="true"/>

lucky的专栏 478

LM Studio 模型加载与转换实战指南:从GGUF格式到本地部署

本文提供了使用LM Studio加载与转换GGUF格式大语言模型的完整实战指南。详细阐述了为何GGUF格式是本地部署的最佳选择,并逐步指导用户如何将非GGUF模型(如Transformers格式)转换为GGUF格式,以及在LM Studio中进行加载、配置GPU卸载等关键优化,最终实现流畅的本地离线对话体验。

weixin_29061425的博客 919

抖音直播参数逆向实战:手把手教你用Python获取ttwid和x-bogus(附完整代码)

本文深入解析抖音直播接口的反爬机制,重点剖析核心防护参数ttwid和x-bogus的生成原理与作用。通过Python实战,手把手教你逆向获取ttwid、webid等关键参数,并构建稳定的数据采集方案,为开发者提供企业级数据获取能力。

weixin_29196891的博客 1044

Java中如何实现负载均衡策略

希望通过本文中提到的各种负载均衡算法和实现,大家可以更好地了解不同负载均衡技术的工作原理和适用场景。也可以根据特定的需求和系统架构选择适合的负载均衡策略,以优化系统性能。在使用负载均衡技术时,请务必考虑系统的动态性、监控和调整、容错和故障处理等因素,以确保系统的稳定性和可靠性。

EverythingAtOnce的博客 2144

解决[WARN] : Controller Spawner couldn‘t find the expected controller_manager ROS interface.思路

rrbot例程ros_control配置问题的解决思路 本人刚入门ROS机器人开发,在学习rrbot例程出现了control_manager无法启动的bug。 在启动rrbot_control.launch的时候,出现下列warning: [WARN] [1594362016.372059]: Controller Spawner couldn't find the expected controller_manager ROS interface. 之后再按教程的步骤 rosservice call /

qq_40299650的博客 1万+

Java实现常见的负载均衡

Java实现常见的负载均衡算法 什么是负载均衡? 负载平衡(Load balancing)是一种电子计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载平衡服务通常是由专用软件和硬件来完成。 主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发和高可用的问题。 常见的负载均衡算法 1

mountain9527的博客 9283

ZYNQ系列PS侧和PL侧DDR3或DDR4在AD(Altium Designer 25)中的layout布线规则约束

DDR3或DDR4的PCB布线规则通常有相对固定的要求,对应的,在PCB设计时有固定的约束设置。

FPGA艺术家的博客 787

用 Custom Entity 打造 RAP Value Help:从能跑到好用的深度踩坑笔记

本文介绍了在RAP项目中实现Value Help(Fiori输入帮助)的完整流程。通过Custom Entity方式,开发者可以灵活构建不依赖数据库实体的值帮助功能,但需手动实现CDS原本提供的过滤、排序、分页等能力。文章以一个典型场景为例,详细说明了如何为Partner维护界面的City字段创建可搜索的值帮助,包括创建查询实现类、绑定CDS Custom Entity、服务发布等关键步骤,并特别指出了处理排序分页请求等常见问题。最后强调在ABAP Cloud环境下需要自行实现查询能力,而非依赖传统工具类。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 137

java学习深度优先算法(未测试)

[Java]代码     package cn.xuhang.collection; import java.util.ArrayList; import java.util.List; /** * 从一个点到达另一个点的路径 * 用到深度优先算法dfs * * @author Hang * */ public class MazePath{ public static L

程序员_007的博客 575

Android 15.0 app进程保活白名单功能实现

在15.0的系统rom产品开发中,在某些重要的app即使进入后台,产品需求要求也不想被系统杀掉进程,需要app长时间保活,就是app进程保活白名单功能的实现, 所以需要在系统杀进程的时候不杀掉白名单的进程,接下来就看怎么样来实现这些功能

安卓兼职framework和app工程师的博客 638

请介绍一些常用的Java负载均衡算法,以实现高并发和高可用性?

请介绍一些常用的Java负载均衡算法,以实现高并发和高可用性?

java1234的博客 1181

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

多种负载均衡算法及其Java代码实现

首先给大家介绍下什么是负载均衡(来自百科)负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web 服务器、 FTP服务器、 企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。 本文讲述的

畅聊架构 584

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

浅谈几种负载均衡(LVS,nginx, HAProxy)

什么是负载均衡(Load balancing) 在网站创立初期,我们一般都使用单台机器对台提供集中式服务,但随着业务量越来越大,无论性能还是稳定性上都有了更大的挑战。这时候我们就会想到通过扩容的方式来提供更好的服务。我们一般会把多台机器组成一个集群对外提供服务。然而,我们的网站对外提供的访问入口都是一个的,比如www.taobao.com。那么当用户在浏览器输入www.taobao.com...

Syd丶 777

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

搞懂分布式技术:LVS实现负载均衡的原理与实践

在实际应用中,在Web服务器集群之前总会有一台负载均衡服务器,负载均衡设备的任务就是作为Web服务器流量的入口,挑选最合适的一台Web服务器,将客户端的请求转发给它处理,实现客户端到真实服务端的透明转发。我们有个中间层啊,对,就是DNS,我们可以设置一下,让我们网站的域名映射到多个服务器的IP,用户面对的是我们系统的域名,然后我们可以采用一种轮询的方式, 用户1的机器做域名解析的时候,DNS返回IP1, 用户2的机器做域名解析的时候,DNS返回IP2……然而,我们的网站对外提供的访问入口都是一个的,比如;

通往IT大道的专栏 770

几种简单的负载均衡算法及其Java代码实现

几种简单的负载均衡算法及其Java代码实现什么是负载均衡负载均衡,英文 名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种 负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。负载均衡能够平均分配客户请求到服 务器阵列,借此提供快...

qq_36083215的博客 261

多种负载均衡算法及其 Java 代码实现

首先给大家介绍下什么是负载均衡(来自百科) 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。 负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web 服务器、 FTP服务器、 企业关键应用服务器和其它关键任务服务器等,从而共同完成

shuizhizhiyin的专栏 405

2台服务器负载均衡后synchronized_手写微服务核心技术——负载均衡算法

概述「负载均衡」是指,通过一定的算法使请求可以均匀的宠幸服务提供方,做到雨露均沾。市面上,软件硬件产品一大把,解决的最最核心的问题都是选谁。分类按实现方式,可以分为硬件负载均衡(如 F5 、A10)、软件负载均衡(如 LVS、Nginx、HAProxy)、DNS 负载均衡。硬件负载均衡和DNS 负载均衡我们不过多关注,重点看一下软件负载均衡。软件负载均衡又分四层和七层负载均衡,四层负载均衡就是在网...

weixin_36046702的博客 354

常见负载均衡算法及java实现

什么是负载均衡负载均衡,英文名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。负载均衡能够平均分配客户请求到服务器阵列,借此提供快速获取重要数据,解决大量并发访问服务问题,这种集群

xinxiaoyong 439

RabbitMQ HAProxy 负载均衡

前面我们学习了 rabbitmq 搭建集群,并且为了解决集群中队列的高可用问题,使用仲裁队列替代普通的队列,但是其实这里还有一个问题,就是我们在使用 Java 连接 rabbitmq 的时候,需要指定 rabbitmq 服务的 IP 和端口号,如果该端口号绑定的 rabbitmq 服务挂掉了,那么我们的 Java 程序是否还能够访问到呢?在RabbitMQ集群中,如果所有客户端都连接到同一个节点,该节点的网络负载会显著增加,而其他节点则可能处于空闲状态,造成资源浪费。

2509_92430044的博客 742

Java 负载均衡之随机和轮询的小方法

import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; /** * 负载均衡,参考ribbon的算法机制 * */ public class LoadBalancerUtil { private final static Random rand; private final ...

Nba_3210的博客 581

一致性hash算法_负载均衡之缓存路由(一致性Hash)算法Java实现

负载均衡之缓存路由(一致性Hash)算法Java实现  分布式系统中负载均衡的问题时候可以使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡的作用。比如说分布式缓存,既然是缓存,就没有必要去做一个所有机器上的数据都完全一样的缓存集群,而是应该设计一套好的缓存路由工具类,所以一致性Hash算法就因此而诞生了。  衡量一个一致性...

weixin_39595537的博客 279

一致性哈希 java实现_一致性哈希算法介绍,及java实现

https://www.cnblogs.com/hupengcool/p/3659016.html应用场景在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least Connection)、响应速度算法(Response Time)、加权法(Weighted )等。其中哈希算法是最为常用的算法.典型的应用场景是:...

weixin_30016593的博客 304

分布式专题(七):负载均衡概念与主流方案

负载均衡的原理 原创: 刘欣 码农翻身 4月23日 这是1998年一个普通的上午。 一上班,老板就把张大胖叫进了办公室,一边舒服地喝茶一边发难:“大胖啊,我们公司开发的这个网站,现在怎么越来越慢了? ” 还好张大胖也注意到了这个问题,他早有准备,一脸无奈地说: “唉,我昨天检查了一下系统,现在的访问量已经越来越大了,无论是CPU,还是硬盘、内存都不堪重负了,高峰期的响应速度越来越慢。” ...

aust_zyl的博客 579
上一篇: Jdk1.8版本并发包基类AQS(AbstractQueuedSynchronizer)实现原理分析
下一篇: Jdk1.8版本CountDownLatch实现源码分析
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值