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

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

 

从加权最小二乘(WLS)到IAA:手把手推导DOA估计中的迭代自适应核心公式 本文深入解析了从加权最小二乘(WLS)到迭代自适应算法(IAA)在DOA估计中的数学推导与应用。通过动态调整加权矩阵,IAA在低快拍数、相干源等复杂场景中展现出卓越性能,显著提升角度分辨率和检测概率。文章详细介绍了算法核心步骤、工程优化策略及前沿发展,为雷达探测和无线通信领域提供重要参考。 阅读详情

相关推荐

【Ubuntu】SMBus Host controller not enabled(虚拟机进入不了图形界面)

SMBus Host controller not enabled(虚拟机进入不了图形界面)

Cappuccino Blog 4万+

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

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

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

StarUML最新版汉化与破解二合一教程:5分钟搞定永久使用

本文提供StarUML最新版的高效使用指南,涵盖从安装到深度定制的全流程优化方案。包括软件获取最佳实践、界面个性化设置、核心建模技巧、团队协作策略及性能优化建议,帮助架构师和开发团队提升UML建模效率。特别推荐版本控制集成和文档自动化输出方案,适用于各类规模的项目开发。

weixin_42530732的博客 451

esl:uniqid=uuid

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

lucky的专栏 478

Ubuntu22.04安装ROS1

代表使用 2 线程进行编译,可以根据 CPU 适当调整。如果出现小乌龟窗口,说明安装成功 🎉!启动成功,则打开另一个终端,测试。需要解决一些兼容性问题,因为。由于 Ubuntu 22.04。过程,确保成功安装。

asafriend的博客 4646

CUDA详细安装及环境配置——环境配置指南 – CUDA+cuDNN+PyTorch 安装

本文详细介绍了如何确定显卡支持的CUDA版本、选择对应的cuDNN版本,并逐步安装CUDA、cuDNN和PyTorch。首先,通过命令行输入nvidia-smi.exe查看显卡支持的CUDA版本。接着,根据CUDA版本选择对应的cuDNN版本并下载。然后,从NVIDIA官方网站下载CUDA安装包,按照提示进行安装,并检查是否安装成功。同样地,下载cuDNN安装包,解压后将文件拷贝到CUDA安装目录中,并通过命令行验证安装是否成功。最后,根据PyTorch官网的指引,选择合适的安装命令进行PyTorch的安装

2501_90350274的博客 5098

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

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

EverythingAtOnce的博客 2144

逐行逐句进一步了解SurroundOcc(一)

通过分析中的模型构建过程,理解了从配置文件到模型实例化的整个流程。构建过程的核心是通过build和等函数,逐步将配置文件解析并生成模型的各个模块对象,最终组合成一个完整的模型结构。这一过程涉及多个类和函数的调用,其中函数是生成对象的关键,它能够从配置字典中提取必要信息并生成对应的类实例。

lovely_yoshino的博客 8111

Java实现常见的负载均衡

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

mountain9527的博客 9283

Linux运维踩坑实录:手把手教你修复LVM中PV显示[unknown]的诡异问题

本文详细解析了Linux运维中LVM物理卷(PV)显示[unknown]的故障现象及修复方法。通过分析问题根源、提供标准修复流程和特殊场景处理方案,帮助运维人员快速解决VG容量异常、PV状态丢失等问题,并分享预防措施与最佳实践,确保LVM存储系统的稳定运行。

weixin_26869081的博客 348

SAP FI 会计科目表(COA)可直接套用配置模板

摘要:本文提供了SAP S/4HANA环境下可直接套用的会计科目表(COA)配置模板,包含科目编码规则、号段规划、科目组设置等核心内容。模板采用10位数字编码,按资产(1000)、负债(2000)、权益(3000)、成本(4000)、收入(5000)、费用(6000)六大类划分号段,并预设科目组控制字段状态。适用于集团/单一公司、国内/跨国企业场景,支持多表架构映射,配置完成后可通过事务码SAKO验证科目清单。模板遵循"前4位固定一级科目"原则,企业可根据行业特性调整明细科目。

金牌架构师 266

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

五步通关!宝塔Linux部署ASP.NET Core的魔法秘籍大公开!

摘要: 本文提供ASP.NET Core应用五步部署攻略,涵盖从环境配置到线上运行的完整流程: 1️⃣ 环境准备:安装宝塔面板、ASP.NET Core运行时及开放端口; 2️⃣ 应用发布:通过dotnet publish生成独立部署包并上传服务器; 3️⃣ Nginx配置:设置反向代理将域名请求转发至应用端口; 4️⃣ 进程守护:使用Supervisor确保应用持续运行; 5️⃣ HTTPS加密:通过宝塔快速申请SSL证书并解决验证路径冲突。 关键点: 强调权限设置(755)、端口开放及反向代理细节; 提

java专栏 969

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

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

java1234的博客 1181

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

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

畅聊架构 584

android 蓝牙通讯demo

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

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

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

Syd丶 777

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

搞懂分布式技术: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、付费专栏及课程。

余额充值