Deploy behind HAProxy - websockets 10.1 documentation
Description: This guide demonstrates a way to load balance connections across multiple websockets server processes running on the same machine with HAProxy. We’ll run server processes with Supervisor as describ...

Hide navigation sidebar
Hide table of contents sidebar
Toggle table of contents sidebar

# Deploy behind HAProxy

This guide demonstrates a way to load balance connections across multiple websockets server processes running on the same machine with HAProxy.

We’ll run server processes with Supervisor as described in this guide.

## Run server processes

Save this app to `app.py`:

    #!/usr/bin/env python

    import asyncio
    import os
    import signal

    import websockets

    async def echo(websocket):
        async for message in websocket:
            await websocket.send(message)

    async def main():
        # Set the stop condition when receiving SIGTERM.
        loop = asyncio.get_running_loop()
        stop = loop.create_future()
        loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)

        async with websockets.serve(
            echo,
            host="localhost",
            port=8000 + int(os.environ["SUPERVISOR_PROCESS_NAME"][-2:]),
        ):
            await stop

    if __name__ == "__main__":
        asyncio.run(main())

Each server process listens on a different port by extracting an incremental index from an environment variable set by Supervisor.

Save this configuration to `supervisord.conf`:

    [supervisord]

    [program:websockets-test]
    command = python app.py
    process_name = %(program_name)s_%(process_num)02d
    numprocs = 4
    autorestart = true

This configuration runs four instances of the app.

Install Supervisor and run it:

    $ supervisord -c supervisord.conf -n

## Configure and run HAProxy

Here’s a simple HAProxy configuration to load balance connections across four processes:

    defaults
        mode http
        timeout connect 10s
        timeout client 30s
        timeout server 30s

    frontend websocket
        bind localhost:8080
        default_backend websocket

    backend websocket
        balance leastconn
        server websockets-test_00 localhost:8000
        server websockets-test_01 localhost:8001
        server websockets-test_02 localhost:8002
        server websockets-test_03 localhost:8003

In the backend configuration, we set the load balancing method to `leastconn` in order to balance the number of active connections across servers. This is best for long running connections.

Save the configuration to `haproxy.cfg`, install HAProxy, and run it:

    $ haproxy -f haproxy.cfg

You can confirm that HAProxy proxies connections properly:

    $ PYTHONPATH=src python -m websockets ws://localhost:8080/
    Connected to ws://localhost:8080/.
    > Hello!
    < Hello!
    Connection closed: 1000 (OK).