{"id":12902,"date":"2016-03-22T11:57:38","date_gmt":"2016-03-22T10:57:38","guid":{"rendered":"https:\/\/touk.pl\/blog\/?p=12902"},"modified":"2022-07-28T16:53:38","modified_gmt":"2022-07-28T14:53:38","slug":"haproxy-sticky-sessions-for-soap-payloads","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2016\/03\/22\/haproxy-sticky-sessions-for-soap-payloads\/","title":{"rendered":"HAProxy load balancing with sticky sessions based on request body"},"content":{"rendered":"<p>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&#8217;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 &#8211; configure a loadbalancer and we are done.<\/p>\n<p>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 <a href=\"http:\/\/www.haproxy.org\/\">HAProxy<\/a> 1.6 and simple <a href=\"http:\/\/www.lua.org\/\">LUA<\/a> script to do just that:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">core.Alert(\"LUA script parsing SOAP element loaded\");\r\n\r\nfunction parseElement(txn, salt)\r\n\r\n    local payload = txn.req:dup()\r\n\r\n    -- parses integer value from element named \"element\"\r\n    local value = string.match(string.match(payload, \"element&gt;%d+&lt;\"), \"%d+\")\r\n    core.Info(\"value: \" .. value)\r\n    return value\r\nend\r\n\r\n-- register HAProxy \"fetch\"\r\ncore.register_fetches(\"parseElement\", parseElement)\r\n<\/pre>\n<p>Put this script into a file and it can be loaded in HAProxy configuration using <a href=\"http:\/\/cbonte.github.io\/haproxy-dconv\/configuration-1.6.html#lua-load\">lua-load<\/a> directive.<\/p>\n<p>Script registers new HAProxy fetch which can be used to configure session stickiness.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">balance\u00a0roundrobin\r\nstick-table\u00a0type\u00a0string\u00a0size\u00a030k\u00a0expire\u00a030m\r\nstick\u00a0on\u00a0\"lua.parseElement\"\u00a0table\u00a0nodes<\/pre>\n<p>You have to also make sure all payload is loaded before you start parsing it. This can be achieved with <a href=\"http:\/\/cbonte.github.io\/haproxy-dconv\/configuration-1.6.html#4-option%20http-buffer-request\">option http-buffer-request<\/a> configuration directive.<\/p>\n","protected":false},"excerpt":{"rendered":"Integrating systems you have no influence on needs a lot of workarounds. Recently we could not scale Python&hellip;\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[594,599,598,600,381,601],"class_list":{"0":"post-12902","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-api","8":"tag-haproxy","9":"tag-loadbalancing","10":"tag-lua","11":"tag-soap","12":"tag-sticky-session"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=12902"}],"version-history":[{"count":12,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12902\/revisions"}],"predecessor-version":[{"id":14684,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12902\/revisions\/14684"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=12902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=12902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=12902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}