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

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

 

GlobalPlatform Technology Secure Channel Protocol ‘03‘ 标准 - 安全通道协议简介 按照GlobalPlatform Technology Secure Channel Protocol '03' (SCP03)标准,描述了如何利用S-MAC,S-RMAC,S-ENC进行安全通信的过程。 阅读详情

相关推荐

批量导入经纬度点到奥维地图中

随便说说 最近出来出差,天天东奔西跑的,跑完了回到酒店还得整理一天的成果,基本上晚上9点才能整理完,累的基本上倒头就睡,没时间鼓捣自己喜欢的东西了。但想着也得写点啥吧,想来想去就那最近工作中用到的东西吧。因为我们现在的工作内容呢,基本上就是按照着上面给的地理位置找到地方开始检查。所以呢,就需要批量的把手上的经纬点信息导入到地图中,安排好路线,利用导航高效的找到地方。给的坐标就是gps点,wgs-84的,使用奥维地图最方便了,不用做坐标转换直接能用。所以作为组里的gis担(苦)当(力),这个导坐标的活就由我来

lionhenryzxxy的博客 3万+

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

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

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

2025年三级等保新规实战:从零开始搭建企业安全防护体系(附完整配置清单)

本文详细解析2025年三级等保新规的核心变化,提供从零开始搭建企业安全防护体系的实战指南。重点介绍动态防护能力、实战化攻防验证和全链路数据保护等关键要求,并附完整配置清单,帮助企业高效合规。

weixin_30836759的博客 468

esl:uniqid=uuid

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

lucky的专栏 478

实战详细讲解Qt插件plugin的编写与用法

qt插件的开发,可以说是动态库的开发,因为调用方式类似,多熟悉一下,利用Qt框架开发很简单的。在想想这种调用过程有的熟悉,比如公司买了一堆摄像头,公司要对摄像头进行二次开发,实现自己想要的功能,集成到一套设备里去,然后在卖给用户。此时厂商肯定会提供开发文档,并给你SDK包(软件开发工具包), 包里你会发现只有头文件和一堆库文件,没有源文件,因为实现的过程是产商公司保密的,给你看还得了。所以都封装成了库的形式给你调用,如静态库或者动态库。

qq_44667165的博客 1万+

EDEM在农业机械设计中的实战应用:以谷物收割机优化为例

本文以谷物收割机优化为例,详细阐述了EDEM离散元仿真软件在农业机械设计中的实战应用。通过构建精准的“数字谷物”模型与农机部件动态界面,利用GPU加速完成大规模颗粒系统仿真,有效诊断并解决了籽粒夹带损失与清选负荷不均等田间难题,实现了从仿真分析到田间验证的设计优化闭环。

weixin_29256771的博客 108

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

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

EverythingAtOnce的博客 2144

FlashAttention 快速安装指南(避免长时间编译)

FlashAttention 编译太慢?本篇提供无需编译的预编译 wheel 快速安装方案,适配多版本 Python、PyTorch 和 CUDA,极大节省部署时间!

Junseer的博客 9719

Java实现常见的负载均衡

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

mountain9527的博客 9283

不止是打字机效果:手把手教你用SpannableStringBuilder打造Android富文本AI对话界面

本文详细介绍了如何使用SpannableStringBuilder在Android平台上构建专业级AI对话界面,涵盖流式文本处理、富文本解析、交互优化等核心技术。通过实战代码示例,帮助开发者实现类似DeepSeek的AI产品交互效果,提升用户体验和应用专业度。

weixin_28358083的博客 198

电子电器架构 --- OEM企标中规定ECU启动时间的目的

电子电器架构 --- OEM企标中规定ECU启动时间的目的

Soly_kun的博客 223

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

Unity3D实现自定义河流路径或泥石流路径

此工具是一个插件,插件很好用,可以根据地形编辑河流的走向以及宽度,也可以发挥想象编辑成其他的效果,比如泥石流效果,岩浆效果,小溪,或者大江或者大河等等博客将会介绍可以编辑河流的工具的使用。希望这篇博客对Unity的开发者有所帮助。大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。提示:以下是本篇文章正文内容,下面案例可供参考本次总结的就是工具的使用, 有需要会继续增加功能不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒!

心疼你的一切博客 5266

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

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

java1234的博客 1181

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

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

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

畅聊架构 584

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

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

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

Syd丶 777

efm32 入门.pdf

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

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

余额充值