unbit/uwsgi — pull request #14 by prymitive (2012-10-05 19:46:31+00:00)
Title: lrc weight handling support

Summary
-------------

This code adds support for weight handling in lrc load balancing algorithm.

Rationale
-------------

There might be some use cases when user wants to favor some nodes if current request rate is low enough that favored nodes can handle it, example:

* spare/backup nodes - user might run few extra servers in case of big load coming, those extra servers might have extra cost when loaded (ec2 instances), so they should not get any requests unless favored nodes can handle the traffic
* complex network topology - some nodes might be located in different data center connected with low or limited bandwidth link, and user might prefer to send requests to local nodes unless they are under high load

Notes
--------

This patch adds new option that enables the use of node weight when deciding what node should get next request, this is disabled by default because:

* wrr and lrc are two different algorithms and weight settings used with one might not be right with other
* Weight handling is optional feature, it's not the integral part of lrc alghorithm. As such it should be enabled by user if needed/applicable.
* It allows user to switch weight handling on/off in one pace (FastRouter), without the need to reconfigure all nodes

Testing
----------

I did some basic testing with weight handling enabled and disabled. I've run ab tests with 3 node cluster where one node had weight set to 10 while others had 1.
With weight handling disabled it acts just like lrc without this patch. Results with weight handling enabled:

* under very low load nodes with reference = 0 will always win and get requests regardless of weight settings. This is just plain math, reference/weight won't ever be lower than 0 and trying to be fair under such conditions would add a lot of complexity.

```
ab -r -c 1 -n 10000

172.16.200.56:3001: weight=1 failcnt=0 wrr=0 requests=3333 ref=0
172.16.200.70:3001: weight=1 failcnt=0 wrr=0 requests=3333 ref=0
172.16.200.55:3001: weight=10 failcnt=0 wrr=0 requests=3334 ref=0
```

* under moderate load where all nodes reference count is > 0 weight value becomes important and this is reflected in the number of requests it gets.

```
ab -r -c 8 -n 10000

172.16.200.70:3001: weight=1 failcnt=0 wrr=0 requests=1324 ref=0
172.16.200.55:3001: weight=10 failcnt=0 wrr=0 requests=7259 ref=0
172.16.200.56:3001: weight=1 failcnt=0 wrr=0 requests=1417 ref=0
```

* under heavy load (average backlog length was 40-50 requests) node weight value makes little difference, favored node had only slightly bigger number of requests. This is correct behavior from lrc algorithm point of view, once node is highly loaded and it can't handle more requests other nodes are being picked.

```
ab -r -c 64 -n 10000

172.16.200.70:3001: weight=1 failcnt=0 wrr=0 requests=3031 ref=0
172.16.200.56:3001: weight=1 failcnt=0 wrr=0 requests=3061 ref=0
172.16.200.55:3001: weight=10 failcnt=0 wrr=0 requests=3908 ref=0
```

Conclusion
---------------

Code works where should (and where it matters) but I'm not entirely sold on the idea. There seem to be valid use cases for it, but I can't decide if this should be in lrc or as separate load balancing algorithm.
I leave You with my mixed feeling about it, it's Your call if You want to merge it or not.
I do not rely on this patch, it's just something I wanted to test so I don't mind if You reject it.