美文网首页
SpringCloud系列之负载均衡Ribbon·12-自定义I

SpringCloud系列之负载均衡Ribbon·12-自定义I

作者: 那钱有着落吗 | 来源:发表于2021-04-24 09:25 被阅读0次
image.png

一致性哈希算法:

image.png

在请求中我们可以使用一致性哈希算法来做负载均衡,如图中,来访的请求我们找一个特征量,可以是url或者参数之类的计算出一个int值,然后这个int值落在这个环上之后,我们需要使用顺时针或者逆时针的方式寻找下一个服务的节点。


public class MyRule extends AbstractLoadBalancerRule implements IRule{

    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    public Server choose(Object key) {

        HttpServletRequest request =
                ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

        String uri = request.getServletPath() + "?" + request.getQueryString();
        return route(uri.hashCode(),getLoadBalancer().getAllServers());
    }


    public Server route(int hashId, List<Server> addressList){
        if(CollectionUtils.isEmpty(addressList))return null;

        final TreeMap<Long,Server> treeMap = new TreeMap<Long, Server>();

        addressList.forEach(server->{
            //虚化若干个服务节点,到环上
            for(int i=0;i<8;i++){
                long hash = hash(server.getId()+i);
                treeMap.put(hash,server);
            }
        });

        long hash = hash(String.valueOf(hashId));

        SortedMap<Long,Server> last = treeMap.tailMap(hash);

        //当requestURL的hash值大于任意一个服务器对应的hashKey,那么就取address中的第一个节点
        if(last.isEmpty()){
            treeMap.firstEntry().getValue();
        }

        return last.get(last.firstKey());

    }


    public long hash(String key){

        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        byte[] keyByte;
        try {
            keyByte = key.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        md5.update(keyByte);
        byte[] digest = md5.digest();

        long hashCode = ( (long)(digest[2] & 0xFF << 16) ) |
                ( (long)(digest[1] & 0xFF << 8) ) |
                 ( (long)(digest[0] & 0xFF) );

        return hashCode & 0xffffffff;
    }
}

如上代码,我们在实现一个自定义的IRule的时候,其实继承一个实现了IRule的抽象类即可,然后重写choose这个方法,可以看出我们重写choose的方法中,使用的就是一致性哈希算法来做的,首先获取到所有的服务,然后给每一台服务增加8个节点,然后使用TreeMap构成了一个环,然后再根据请求的URL再计算出一个hashCode,然后在环上查到下一个服务节点即可,这就完成了一致性哈希算法的负载均衡。

相关文章

网友评论

      本文标题:SpringCloud系列之负载均衡Ribbon·12-自定义I

      本文链接:https://www.haomeiwen.com/subject/mmzzlltx.html