On Sunday, September 11, 2016 9:11:50 AM EDT Willy Tarreau wrote:
> Don't worry, that's the principle of a PoC. I looked at your code. I think
> we can significantly simplify it. The current server's relative capacity
> should be computed on the fly when trying to pick the server in the ring.
> Right now you call this function chash_update_server_capacities() to
> recompute all servers capacities before chosing your server but given that
> you already have the information on the number of total served connections
> in the backend, it's possible to modify the current lookup function to
> void running this loop first. This is especially important as some setups
> have very large numbers of servers (eg: up to 1000).

I agree that this would be better, but the algorithm is supposed to distribute 
the capacity among servers in a particular way. Concretely, say that the 
computed capacity is 14 and there are 10 servers. Then there should be 4 
servers with a capacity of 2 and 6 servers with a capacity of 1, and which are 
which shouldn't depend on where the request hashed to — there needs to be some 
way of identifying the "first" 4 servers. Walking the hash ring seems like an 
inefficient way to do it, I agree, but I didn't have a better one.

> Also I've been thinking about this issue of the infinite loop that you
> solved already. As long as c > 1 I don't think it can happen at all,
> because for any server having a load strictly greater than the average
> load, it means there exists at least one server with a load smaller than
> or equal to the average. Otherwise it means there's no more server in
> the ring because all servers are down, and then the initial lookup will
> simply return NULL. Maybe there's an issue with the current lookup
> method, we'll have to study this.

Agreed again, it should be impossible as long as c > 1, but I ran into it. I 
assumed it was some problem or misunderstanding in my code.

> For the next steps, I would suggest you to try to proceed this way :
> 
> 1) modify all places which adjust srv->served to also adjust
>    srv->proxy->served (I thought it was already done but not). This
>    way you always know the amount of connections being served for a
>    given backend.

Easy enough.

> 2) call a function in your while() loop to check each server's eligibility
>    based on the C parameter. We should consider that C==0 implies the
>    mechanism is not used. This would give something approximately like
>    this :
> 
>    while (c && !ch_server_is_eligible(s, c)) {
>       s = next(s);
>       ...
>    }
> 
>    And this function ch_server_is_eligible() would check that the
>    number of served connections is lower than the total number of
>    served connections in the backend divided by the number of servers
>    currently in use :
> 
>       s->served <= c * s->proxy->served /
>          (s->proxy->srv_act ? s->proxy->srv_act :
>           s->proxy->lbprm.fbck ? 1 : s->proxy->srv_bck)

Agreed, except for the caveat I mentioned above.

> 3) add a configuration option. I still don't know if it would be better
>    in the backend or in the server. I'm tempted to think it's better to
>    have it per backend (to avoid the risk that no server it picked) and
>    to let people continue to use the weights to modulate the acceptation
>    ratio as they've always been doing.
> 
> This last point makes me think that we should probably use "c * s->weight"
> instead of just "c" so that each server's weight is considered in this
> ratio. This is quite important otherwise in practice it will not be much
> possible to apply different weights to servers.

I will have to think on how to do the weights properly, and I will probably do 
my first stab without them, but I do follow your logic.

As for the configuration parameter, it's okay to add a double and use atof? 
Normally I wouldn't ask, but since haproxy has no floats at all I'm double-
checking before introducing them.

Thanks,

Andrew


Reply via email to