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

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

 

fpga在线升级 linux_仅5000行Verilog代码、可在FPGA上跑轻量级Linux系统的RISC-V内核 本文发布于www.hackster.io,由东京理工大学的计算机学院开发,专用于教学与加速用(苏老师也一直认为这是RISC-V当前的主要方向)。目前市场上开源的RISC-V内核已经很多,但很少有公开的RISC-V计算系统是非常轻型且能跑Linux系统的。这一款RISC-V内核就可以运行在FPGA上,用Verilog编写的,需要很少硬件的资源就能跑起来,所以可以运行在一个低成本的FPGA上。来看一下... 阅读详情

相关推荐

数字IC后端笔记-libcell命名规则与标准单元库介绍

ND3D1BWP13T40P140HVTND3D1BWP13T40P140HVTTSMC两种工艺,Metalization Stack的截面示意图:还有一层AP用来走RDL,RDL这层是最厚的一层,一般用于连接IO的bump,信号线基本上不会用这层绕线。

sinat_41774721的博客 2464

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

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

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

【主力资金密码】副图指标升级版使用技术图文案例分解,通达信软件炒股指标公式代码

(1)主力资金线在低位时,对应的副图指标显示柱线是绿色,这个阶段主力资金参与小,行情处于下跌趋势或弱势震荡。当然,如果结合主图指标【翻倍密码系统】操作,主图的两个买卖点以及K线均线变色跟踪功能,更多的技术支撑,多空更加清晰,共振做多或多头更加确定和安全。如上图标记,中档虚线是参考安全操作的一个区间划分,粉色阶段做多或持股为主,为操作增加一道安全保护。如上图,副图指标【主力资金密码】更新叠加操作区间背景,绿色阶段持币或做空,粉色阶段做多或持股。如上图,副图指标,标记的两个区间,绿色区间时做空或持币。

weixin_69760830的博客 2553

esl:uniqid=uuid

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

lucky的专栏 478

如何下载era5数据?(两种方式)

供水利大数据云计算课程同学参考使用#

Camiel_sweet的博客 1万+

西门子S7-1200与S7-200SMART的PROFINET通讯实战:从GSD文件生成到数据监控

本文详细解析了西门子S7-1200与S7-200SMART之间实现PROFINET通讯的完整实战流程。核心内容包括将S7-200SMART配置为智能IO设备、生成并安装GSD文件、在TIA Portal中进行网络组态与地址映射,最终实现双向数据交换与监控。该方案为整合新旧设备、构建灵活高效的工业自动化系统提供了可靠路径。

weixin_29271263的博客 245

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

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

EverythingAtOnce的博客 2144

【DRAM存储器四十七】LPDDR5介绍--LPDDR5的低功耗技术之DVFS

讲述LPDDR5的DVFSC和DVFSQ的工作原理和要求

highman110的博客 900

Java实现常见的负载均衡

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

mountain9527的博客 9283

大数据与宠物:健康监测数据分析

随着全球宠物市场规模的快速增长(2023年全球宠物产业规模已达3500亿美元),宠物健康管理需求呈现指数级上升。传统宠物医疗依赖定期体检和症状观察,存在滞后性和主观性缺陷。本文聚焦如何通过物联网(IoT)设备采集宠物生理数据(体温、心率、活动量等),利用大数据分析技术构建实时健康监测系统,实现宠物健康状态的动态评估、异常预警和疾病预测。研究范围涵盖数据采集技术、数据预处理方法、机器学习模型构建及实际应用场景落地。背景介绍:明确研究目的、目标读者及核心术语核心概念与联系。

2502_91592937的博客 1067

完整的 Python 数据分析案例:新能源汽车续航里程预测

随着新能源汽车的普及,续航里程成为消费者关注的重要指标。准确预测新能源汽车的续航里程,有助于车企优化电池管理系统、提升车辆性能,也能帮助消费者合理规划出行。本案例将基于新能源汽车的各项参数,如电池容量、行驶速度、环境温度等,构建续航里程预测模型。通过以上改进,可以提高数据处理的准确性、模型的性能和可视化的效果。

daqsdfas的博客 1588

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

把时间当成数据:SAP ABAP 里的 DATS/TIMS 与 DATN/TIMN,怎么选才不踩坑

SAP项目中日期时间字段的陷阱与优化 日期时间字段(DATS/TIMS)在SAP项目中看似简单却常引发事故,主要问题包括: 非法日期(如20201331)入库后,在月结、对账时爆发异常 空值被处理为00000000导致排序错误 ABAP提供两种处理方案: 经典类型DATS/TIMS:存储为字符格式,校验宽松易存脏数据 HANA原生类型DATN/TIMN:数据库级校验,写入即拦截非法值 优化建议: 在接口层和入库前进行严格校验 新项目优先使用DATN/TIMN类型 对遗留数据使用DATS_IS_VALID等函

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

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

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

java1234的博客 1181

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

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

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

畅聊架构 584

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

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

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

Syd丶 777

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

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

余额充值