美文网首页
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