Published on

What is HAProxy ?

Authors

Target Audience

I've aimed this article at people who want to learn about HAProxy, Docker, Containers, Node.js.

Learning Objectives

After completing this article, you will know how to do the following:

  • Create a simple node.js application and docker image for it.
  • Create and setup HAProxy configuration and docker image for it
  • Setup docker-compose.yml configuration.
  • Use docker compose to start the entire application.
  • Make API calls to test the HAProxy.

What is HAProxy ?

Wiki Definition

HAProxy is a free and open source software that provides a high availability load balancer and reverse proxy for TCP and HTTP-based applications that spreads requests across multiple servers.It is written in C and has a reputation for being fast and efficient (in terms of processor and memory usage). src

Configuration

Frontend

When HAProxy is used as a reverse proxy in front of backend servers, a frontend section defines the IP addresses and ports that clients can connect to. You may add as many frontend sections as needed to expose various websites or applications to the internet. src

# haproxy.cfg file

frontend myapp
	mode http # proxy mode --> http(layer 7), tcp(layer 4)
	bind *:80 # listen all ip adresses with port number 80
	default_backend myserver # default pool of backend servers
...

The "mode" of the "backend" section that receives traffic from a "frontend" section should be the same. The configuration won't work if there's a mismatch.

Backend

HAProxy frontend sections accept incoming connections that can then be forwarded to a pool of servers. The backend section is where those pools of servers that will service requests are defined.src


# haproxy.cfg file

#backend section
backend myserver
	mode http # mode has to be same as frontend
	server s1 localhost:11
	server s2 localhost:22
	server s3 localhost:33


Health Checking

HAProxy keeps only healthy servers in the load-balancing rotation. It checks the status of each server by using one of the health checking modes described in this section.

You can see the example configuration for health check below:

backend myserver
	mode http
	option httpchk # enable http health check

	server s1 localhost:80 check
	server s2 localhost:81 check
	server s3 localhost:82 check

Timeout

If you’re unsure as to what it means, it’s simple: when hitting a timeout, your first reaction should not be to increase the timeout. You should investigate why something is taking so long that you hit a timeout somewhere and fix the root cause

You can check out the basic HAProxy timeouts in the table below:

nameexplanation
timeout clientSet the maximum inactivity time on the client side.
timeout connectSet the maximum time to wait for a connection attempt to a server to succeed.
timeout serverSet the maximum inactivity time on the server side.

Configuration file for this demo

We will use this configuration for demo.

defaults
	mode http
	timeout client 10s
	timeout server 10s

frontend f
	bind *:80
	default_backend servers

backend b
	server s1 127.0.0.1:1111
	server s2 127.0.0.1:2222
	server s3 127.0.0.1:2222

Creating simple HTTP server

We will create a simple HTTP web sever using node.js and http library.

Take the following steps to create node.js application: 1- create app folder 2- create index.js file and copy & paste the following code

  • index.js file:
const http = require('http')

const defaultPort = 1111
const portNumber = process.env.PORT || defaultPort

const httpServer = http.createServer((req, res) => {
  res.statusCode = 200
  res.end('Hi, listening on port: ' + portNumber)
})

httpServer.listen(portNumber, '0.0.0.0', () => {
  console.log(httpServer.address())
})

3- Create package.json

You can create package.json file using the following command

npm init -y # yes to skip every question

4- install the http library

You can install a node package using npm install command

npm i http

Dockerfile for HAProxy and Node.js App

We will use docker to run HAProxy and Node.js servers, and we will test our application using simple HTTP requests.

Dockerfile for Node App

You can copy & paste the following snippet to create a docker image for node.js application.

FROM node:13
WORKDIR /home/node/app
COPY app /home/node/app
RUN npm install
CMD npm run app

To create a docker image, use the following command:

docker build -t nodeapp .

Dockerfile for HAProxy

FROM haproxy
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
CMD ["haproxy", "-f", "/usr/local/etc/haproxy/haproxy.cfg"]

To create a docker image, use the following command:

docker build -t haproxy .

Test Docker images

You can test docker images using docker run command.

docker run -p 8080:8080 nodeapp

This will run our node.js application on port 8080. You can use curl request to test the application.

curl -v localhost:8080

Docker compose

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services. src

#docker-compose.yml
version: "3"
services:
  app1:
    image: app
    environment:
      - PORT=1111
    ports:
      - "1111:1111"
  app2:
    image: app
    environment:
      - PORT=2222
    ports:
      - "2222:2222"
  app3:
    image: app
    environment:
      - PORT=3333
    ports:
      - "3333:3333"
  haproxy:
    image: haproxy
    ports:
      - "80:80"
    volumes:
      - ./haproxy:/usr/local/etc/haproxy

Type the following command to start entire application(node.js and haproxy server):

docker compose up

This will run the entire application, and now you can test the application making simple HTTP requests. HAProxy by default use round-robin algorithm to handle which servers will be selected when requests come.

Example logs in docker:

haproxy_test-app1-1     | { address: '0.0.0.0', family: 'IPv4', port: 1111 }
haproxy_test-app3-1     | { address: '0.0.0.0', family: 'IPv4', port: 3333 }
haproxy_test-app2-1     | { address: '0.0.0.0', family: 'IPv4', port: 2222 }

As you can see, we can see that our three node.js applications started, and we can make request.

You can see the codes here:

https://github.com/eminvergil/haproxy-test