I am in REST API Application Gateway implementation of weighted round-robin method in load Balancing

Source: Internet
Author: User
Tags nginx reverse proxy


Recent projects need a REST API application gateway, so with go write one, the function is in continuous improvement, feel the final function is similar to Nginx reverse proxy, in addition to business processing. The configuration is now implemented to control the forwarding behavior. Request the front-end definition of address A, after authentication, go to the backend to specify address B, and return the results.

Support for multiple backend is now increased, so load balancing is achieved.

Probably read the next Nginx source code algorithm, and other netizens, is basically real-time calculation, the final fall to the order of backend, are sequential.

For example, the Netizen's example:

{A, B, c} three servers, weight value is {5, 1, 2}

The selected server order for weighted polling is: A,c,a,a,b,a,c,a

Once the poll is over, repeat it again and again.

So it seems that every time you calculate the weight to get backend is not necessary, rather than the order to get backend to calculate, put in the queue, in order to take the good.


For the above example, the basic idea of my implementation is:

1. Reads the configuration file at startup and is turned on, putting all backend into the queue Masterq,

  For example three Backend:masterq=[0:backend1 , 1:backend2 , 2:backend3 ]

  If it is using weighted round-robin algorithm, initialize weighted round robin algorithm object

2. initialize weighted round-robin algorithm object.

weight_sum ]

MASTERQ index

  upset roundrobinq order, algorithm self-defined: roundrobinq=[1 0 1 0 2 0 1 0 2 0]

3. To get a backend when each request arrives, execute the next method:

  directly from according to current roundrobinq index value, get masterq available in backend:

 backend = masterq[roundrobinq[index]"

  get after index++


Above. In this case, there is less computational capacity per request to get a backend.

Of course, I am thinking of a change of thinking and implementation, and seems to be relatively simple.


here is the first version of the code snippet, you can refer to, has supported the backend to remove the unusable:

Load Balancer configuration information type lbconf struct {BaseUrl stringweight intcookie stringmaxfails int//connected several times after marking for the connection is not available failtime The out int//connection exceeds the number of seconds after which the connection is not available backup INT//Whether backup server 0:no, 1:yes}//load balancer backend information type lbnode struct {Conf lbconfd own boolfails int//number of consecutive failures, succeeded with 0LastDownTime Int64}func (this *lbnode) Setfail () {this. Fails++if this. Fails > this. Conf.maxfails {this. Down = truethis. Lastdowntime = time. Now (). Unix ()}}//load Balancing algorithm interface, different algorithms implement this interface can be type Lbinterface interface {Init () Next (req *http. Request) *lbnode}//Load Balancer Runtime//Save common configuration information type lbruntime struct {LB int//load balance type MASTERQ []*lbnode//Available node BA CKUPQ []*lbnode}func (This *lbruntime) Next (Req *http. Request) *lbnode {return Nil}func (this *lbruntime) Init () {}//load Balancer implementation: Weighted round-robin//specific can refer to the implementation of Ngnix.     Here the implementation of a somewhat different way, not so complex//implement Lbinterface interface, inherit lbruntimetype lbrountrobin struct {lbruntimeroundrobinq []int//round robin queue Rbindex int//Current roundrobinq subscript mqlen int//masterq Queue Length Rqlen int//roundrobinq Queue Length}Gets the next node//based on the initialized weighted round robin queue, sequentially loops through the back end node func (this *lbrountrobin) Next (req *http. Request) *lbnode {if this. Rqlen = = 1 {c: = this. Masterq[this. Roundrobinq[0]]if C.down {this. Rqlen = 0return Nil}return C} else if this. Rqlen > 1 {//Multithreading here will be unsafe (when other threads call Init), but accept//copy to prevent concurrent modification, prevent subscript index: = this. Rbindexthis.rbindex++if this. Rbindex >= this. Rqlen {this. Rbindex = 0}if Index >= this. Rqlen {index = 0}c: = this. Masterq[this. Roundrobinq[index]]if C.down {//If down, regenerate the available queue, remove a node this. Init () return this. Next (req)}return C}//todo does not have a master node, select an alternate node return nil}//initialize Round-robin load balancer//based on the weighted round the results are periodic loops, where the initialization is simple to implement a periodic cycle of the queue// Instead, the func (this *lbrountrobin) Init () {weight_sum: = 0numQ: = 0if Len (this) is computed as nginx when each request arrives. MASTERQ) < 1 {//If there is no backend node, return directly to Return}for _, Node: = Range this. MASTERQ {if node. Down {//filter out hung nodes continue}numq++weight_sum + = node. Conf.weight}if Numq = = 0 {this. Rbindex = 0this. Rqlen = 0this. Mqlen = Len (this. MASTERQ) this. Roundrobinq = Nillog. Info ("Round Robin Q: []") return}//puts the subscript of each execution in the queue,You can do it in order if numq = = 1 {this. Roundrobinq = Make ([]int, 1)} else {this. Roundrobinq = Make ([]int, weight_sum)}w: = 0for key, node: = Range this. MASTERQ {if node. Down {//filter out the Hung nodes, select only the nodes that are not hanging continue}if Numq = = 1 {this. Roundrobinq[0] = Keybreak} else {for i: = 0; i < node. Conf.weight; i++ {this. Roundrobinq[w+i] = key}}w = w + node. Conf.weight}if numq > 1 {//scrambled Roundrobinq order TODO improved r: = Rand. New (Rand. Newsource (time. Now (). Unixnano ()))) for I: = 0; i < weight_sum; i++ {x: = R.INTN (weight_sum) Temp: = this. Roundrobinq[x]other: = weight_sum% (x + 1) this. ROUNDROBINQ[X] = this. Roundrobinq[other]this. Roundrobinq[other] = temp}}this. Rbindex = 0this. Rqlen = Len (this. ROUNDROBINQ) this. Mqlen = Len (this. MASTERQ) log. Info ("Round Robin Q:", this.) ROUNDROBINQ)}


I am in REST API Application Gateway implementation of weighted round-robin method in load Balancing

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.