HAProxy load balancing with sticky sessions based on request body

Integrating systems you have no influence on needs a lot of workarounds. Recently we could not scale Python service consuming SOAP messages with a new hardware. It just didn’t benefit from more processing cores. On the other hand (and this happens often with older software) setting up several instances gave almost linear scalability. Only thing left – configure a loadbalancer and we are done.

Easier said than done. We had to make sure messages are loadbalanced but also that all messages related to given customer USSD conversation always hit the same backend service. So, we had to use application layer information to configure sticky sessions. This is not straightforward in HAProxy when you have to look into http payload and parse some specific information. We used HAProxy 1.6 and simple LUA script to do just that:

core.Alert("LUA script parsing SOAP element loaded");

function parseElement(txn, salt)

    local payload = txn.req:dup()

    -- parses integer value from element named "element"
    local value = string.match(string.match(payload, "element>%d+<"), "%d+")
    core.Info("value: " .. value)
    return value
end

-- register HAProxy "fetch"
core.register_fetches("parseElement", parseElement)

Put this script into a file and it can be loaded in HAProxy configuration using lua-load directive.

Script registers new HAProxy fetch which can be used to configure session stickiness.

balance roundrobin
stick-table type string size 30k expire 30m
stick on "lua.parseElement" table nodes

You have to also make sure all payload is loaded before you start parsing it. This can be achieved with option http-buffer-request configuration directive.

You May Also Like

Context menu or Action buttons ?

Recently I was drawn into one of those UI "religious" disputes that has no easy answers and usually both sides are right. One of our web developers was trying out new web tech (with pretty rich widget library) and started to question himself about some basic usability decisions. The low level problem in this case is usually brought to "which widget should I use ?". I'm not fond of bringing the usability problems to questions: Should I use Tabs over Menu ? Or should I use Context menu instead of buttons panel ? But sometimes if time is crucial factor and other usability levels are by default not addressed at all - better developer that asks those basic questions than developer that do not question himself at all.