Dubbo Load Balancing: Implementation analysis of consistent hash

Source: Internet
Author: User
Tags getmessage hash md5

LoadBalance is responsible for selecting specific one from multiple invoker for this call to apportion pressure. The loadbalance structure in Dubbo is shown below.

 
the Com.alibaba.dubbo.rpc.cluster.LoadBalance interface provides
<T> invoker<t> Select (list<invoker<t >> invokers, url url, invocation invocation) throws rpcexception; 
By this method, node selection is done.
Com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance 
implements a number of public methods, and defines abstract methods
protected Abstraction <t > invoker<t> doselect (list<invoker<t>> invokers, url url, invocation invocation); 
This method is implemented by the concrete load Balancer implementation class.
consistent hash load Balancing configuration

The specific load Balancer implementation class consists of 4 types. are random, rotation, least active, consistent hash.

Consistent hash load balancing configuration, there are several forms.

Configuration such as:

<dubbo:service interface= "..." loadbalance= "Consistenthash"/>
or:

<dubbo:reference Interface= "..." loadbalance= "Consistenthash"/>
or:

<dubbo:service interface= "..." >
    <dubbo : Method Name= "..." loadbalance= "Consistenthash"/>
</dubbo:service>
or:

<dubbo:reference Interface= "..." >
    <dubbo:method name= "..." loadbalance= "Consistenthash"/>
</dubbo:reference >

Consistent hash load balancing involves two main configuration parameters for hash.arguments and hash.nodes.

hash.arguments : When a call is made, the key is generated according to which parameters of the calling method, and the call node is selected by the consistent hash algorithm based on key. For example, Invoke method Invoke (String s1,string S2); If Hash.arguments is 1 (the default), only invoke parameter 1 (S1) is taken to generate the hashcode.

hash.nodes: The number of replicas for the node.

The default is only the first parameter hash, if you want to modify, configure
<dubbo:parameter key= "hash.arguments" value= "0,1"/>

default with 160 copies of the virtual node, if you want to modify, configure
<dubbo:parameter key= "hash.nodes" value= "/>"
The realization analysis of consistent hash in Dubbo

The Dubbo consistency hash is implemented by the Consistenthashloadbalance class.

The consistenthashloadbalance internally defines the Consistenthashselector class, which ultimately makes the node selection through that class. Consistenthashloadbalance implements the Doselect method to take advantage of the created Consistenthashselector object selection node.

The implementation of Doselect is as follows. When the method is called, it is created if the selector does not exist. The node is then selected via the Consistenthashselector Select method.

    @SuppressWarnings ("unchecked") @Override protected <T> invoker<t> doselect (list<invoker<t&gt ;> invokers, url url, invocation invocation) {//Get Call Method name String key = Invokers.get (0). GETURL (). Getserv
        Icekey () + "." + Invocation.getmethodname ();
        Generate call list hashcode int identityhashcode = System.identityhashcode (invokers); To invoke the method named key, get the consistency hash selector consistenthashselector<t> selector = (consistenthashselector<t>) selectors.
        Get (key); Create new selector if not present if (selector = = NULL | | Selector.getidentityhashcode ()! = Identityhashcode) {//Create con Sistenthashselector generates all virtual nodes selectors.put (key, New consistenthashselector<t> (Invokers, Invocation.getm
            Ethodname (), Identityhashcode));
        Get selector selector = (consistenthashselector<t>) selectors.get (key);
    }//Select node return selector.select (invocation); }

Consistenthashselector creates replicanumber virtual nodes inside the constructor and stores these virtual nodes in TreeMap. The key is then generated based on the parameters of the calling method, and a node is selected for invocation in TreeMap.

   Private static Final class Consistenthashselector<t> {private Final Treemap<long, INVOKER&LT;T&GT;&G T Virtualinvokers;   Virtual node private final int replicanumber;                     Number of copies private final int identityhashcode;//hashcode private final int[]   Argumentindex; Parameter index array public consistenthashselector (list<invoker<t>> invokers, String methodName, int identityhas
            Hcode) {//create TreeMap to save node this.virtualinvokers = new Treemap<long, invoker<t>> ();
            Generate Call node Hashcode This.identityhashcode = System.identityhashcode (invokers); Get the URL//Dubbo://169.254.90.37:20880/service. Demoservice?anyhost=true&application=srcanalysisclient&check=false&dubbo=2.8.4&generic=false &interface=service. demoservice&loadbalance=consistenthash&methods=sayhello,retmap&pid=14648&sayhello.timeout=20000&side=consumer&timestamp=1493522325563 URL url = invokers.get (0). GETURL (); Gets the configured node number, if not set, using the default value of This.replicanumber = Url.getmethodparameter (MethodName, "Hash.nodes",
            160); Gets the parameter array index that needs to be hashed, defaults to the first argument hash string[] index = Constants.COMMA_SPLIT_PATTERN.split (url.getmethodparamete
            R (MethodName, "hash.arguments", "0"));
            Argumentindex = new Int[index.length];
            for (int i = 0; i < index.length; i + +) {Argumentindex[i] = Integer.parseint (Index[i]); }//Create virtual nodes//Generate Replicanumber virtual nodes for each Invoker and store them in TreeMap for (invoker<t> Invok Er:invokers) {for (int i = 0; i < REPLICANUMBER/4; i++) {//per 4 nodes based on the MD5 algorithm generates one
                    Message digest with a digest length of 16 bytes and 128 bits.
                    Byte[] Digest = MD5 (Invoker.geturl (). tofullstring () + i); The 128 bits are then divided into 4 parts, 0-31,32-63,64-95,95-128, and generate 4 32-digit numbers, stored in long, Long's high 32 bits are 0//and as a virtual node key.
                        for (int h = 0; h < 4; h++) {Long m = hash (digest, h);
                    Virtualinvokers.put (M, invoker); }}}} public int Getidentityhashcode () {return identityhashcod
        E
            }//Select node public invoker<t> Select (invocation invocation) {//Generate key based on call parameters
            String key = Tokey (Invocation.getarguments ());
            Generate message digest based on this parameter byte[] Digest = MD5 (key);
            Call the hash (digest, 0) and convert the message digest to Hashcode, where only 0-31 bits are generated to generate Hashcode//Call Sekectforkey Method selection node.
            invoker<t> Invoker = Sekectforkey (hash (digest, 0));
        return invoker;
            } private String Tokey (object[] args) {StringBuilder buf = new StringBuilder ();
       Because Hash.arguments is not configured, it takes only the 1th parameter of the method as the key     for (int i:argumentindex) {if (i >= 0 && i < args.length) {buf.
                Append (Args[i]);
        }} return buf.tostring (); }//Select node private invoker<t> sekectforkey (long hash) according to hashcode {invoker<t> invoke
            R
            Long key = hash; If the hashcode is directly the same as a key of a virtual node, return to the node if (!virtualinvokers.containskey (key)) {//If not consistent, find a minimum last
                The node that corresponds to the key.
                Sortedmap<long, invoker<t>> tailmap = Virtualinvokers.tailmap (key); If there is a return, for example Hashcode falls in the figure [1]//If not present, for example, Hashcode falls in the position of [2], then select the first node in TreeMap//use TreeMap F
                Irstkey method to select the minimum upper bound.
                if (Tailmap.isempty ()) {key = Virtualinvokers.firstkey ();
                } else {key = Tailmap.firstkey (); }} invoker = VirtualinvokErs.get (key);
        return invoker; } Private long hash (byte[] digest, int number) {return ((long) (digest[3 + number * 4] & 0xFF) << 24) | ((long) (digest[2 + number * 4] & 0xFF) << 16) | ((long) (digest[1 + number * 4] & 0xFF) << 8) | 
                    (digest[0 + number * 4] & 0xFF))
        & 0xFFFFFFFFL;
            } private byte[] MD5 (String value) {messagedigest MD5;
            try {MD5 = messagedigest.getinstance ("MD5");
            } catch (NoSuchAlgorithmException e) {throw new IllegalStateException (E.getmessage (), E);
            } md5.reset ();
            byte[] bytes = NULL;
            try {bytes = value.getbytes ("UTF-8");
            } catch (Unsupportedencodingexception e) {throw new IllegalStateException (E.getmessage (), E);
    }        Md5.update (bytes);
        return Md5.digest (); }

    }

The hash (byte[] digest, int number) method in the above code is used to generate hashcode. The function converts the resulting result to a long class, because the resulting result is a 32-bit number, which can be negative if saved with an int. The logical ring generated by the consistent hash is hashcode in the range of 0-max_value. Therefore, it is a positive integer, so this is to cast to a long type, avoiding negative numbers.

The node selection method is select, and finally the node is selected by the Sekectforkey method.

        Select node Public
        invoker<t> Select (invocation invocation) {
            //based on the invocation parameter to generate key
            String key = Tokey ( Invocation.getarguments ());
            Generate message digest based on this parameter
            byte[] Digest = MD5 (key);
            Call the hash (digest, 0) and convert the message digest to Hashcode, where only 0-31 bits are generated to generate hashcode
            //Call Sekectforkey Method selection node.
            invoker<t> Invoker = Sekectforkey (hash (digest, 0));
            return invoker;
        }

The Sekectforkey method is implemented as follows.

 private invoker<t> Sekectforkey (long hash) {invoker<t> Invoker;
            Long key = hash; If the hashcode is directly associated with a virtual node key, return to the node if (!virtualinvokers.containskey (key)) {//If not, find a minimum previous
                The node that the key corresponds to.
                Sortedmap<long, invoker<t>> tailmap = Virtualinvokers.tailmap (key); If there is a return, for example Hashcode falls in the figure [1]//If not present, for example, Hashcode falls in the position of [2], then select the first node in TreeMap//use TreeMap F
                Irstkey method to select the minimum upper bound.
                if (Tailmap.isempty ()) {key = Virtualinvokers.firstkey ();
                } else {key = Tailmap.firstkey ();
            }} invoker = Virtualinvokers.get (key);
        return invoker; }

When making a selection, if the hashcode is directly the same as the key of a virtual node, the node is returned directly, for example, Hashcode falls on a node (represented by a circle). If not, find the node that corresponds to the smallest last key. For example, when making a selection, the key falls in the position indicated in Figure 1. Due to the use of treemap storage, the position where key falls may not be able to find the minimum upper bounds, such as the position indicated in Figure 2. Then it is necessary to return the minimum value in the TreeMap (which makes up the logical ring structure, which is not found, and returns the most initial node).
Reference

Dubbo 2.8.4 Source

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.