Skip to content

Instantly share code, notes, and snippets.

@sqlbot
Last active January 8, 2022 17:20
Show Gist options
  • Save sqlbot/a440bd53cd2d1cde67a9 to your computer and use it in GitHub Desktop.
Save sqlbot/a440bd53cd2d1cde67a9 to your computer and use it in GitHub Desktop.
Custom failure message to MySQL clients when no backends are available with HAProxy 1.6 with Lua
-- With the addition of Lua to HAProxy 1.6, we can generate a custom error message
-- to any client requesting a connection, identifying the proxy that returned the error
-- by its ec2 instance ID (or any other meaningful identifier in your environment),
-- providing a cleaner method of reporting failure to the caller than just opening and closing the connection,
-- which would be the default behavior with no backend servers healthy, and could lead to
-- troubleshooting the wrong thing.
-- the response packet we craft is a valid packet in the MySQL client/server protocol,
-- so any client should understand and be able to report the error back up the stack; viz.:
-- $ mysql --host 127.0.0.1 --port 3306
-- ERROR 1053 (HY000): connection succeeded to haproxy at i-a20fc4ac but no healthy MySQL servers are available to provide the requested service
-- A client that interprets the actual return code will translate it as
-- Server shutdown in progress (ER_SERVER_SHUTDOWN)
-- The error code was chosen arbitrarily as something that would indicate that no connection was possible
-- for a reasonably convincing reason; choose a different error code if you like.
-- given the following prerequisites:
-- in /etc/init.d/haproxy, we set the environment variable before HAProxy starts up
-- export EC2INSTANCEID=$(/usr/bin/ec2metadata --instance-id)
-- in /etc/haproxy/haproxy.cfg
-- global
-- lua-load /etc/haproxy/mysql-err.lua
-- myfrontend
-- tcp-request content lua mysql_unavailable if { nbsrv(mybackend) lt 1 }
-- in /etc/haproxy/mysql-err.lua:
function mysql_unavailable(txn)
local ec2id = os.getenv("EC2INSTANCEID")
local error_code = 1053 -- "mysql server is shutting down," maybe helpful for clients that interpret the code instead of the text
local error_message = "connection succeeded to haproxy at " .. ec2id .. " but no healthy MySQL servers are available to provide the requested service"
local payload = string.pack("I1<I2",255,error_code) .. error_message
local response = string.pack("<I4",string.len(payload)) .. payload
txn.res:send(response)
txn:close()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment