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