Basic load balancer with NGINX

Basic load balancer with NGINX

Table of contents

No heading

No headings in the article.

NGINX is an advanced web browser that can be used as a reverse proxy, load balancer, mail proxy, and caching mechanism. In this short tutorial, we scale a golang REST API service with docker-compose and distribute all the load from the client to these multiple service instances.

nginx-load-balancer.png

The client makes an API call to http://localhost:8000/ endpoint, which hits the nginx service that internally proxies the request to one of the 3 instances of the REST servers running on the port 8000. We will be using the Round robin load-balancing technique that can help us to almost evenly distribute the load across every instance.

  1. build golang servers image with Dockerfile

     FROM golang:1.18-alpine AS builder
    
     RUN mkdir /app
     WORKDIR /app
     COPY . .
    
     RUN CGO_ENABLED=0 GOOS=linux go build -o app cmd/api/main.go
    
     FROM alpine:latest AS production
     WORKDIR /app
     COPY --from=builder /app/app .
    
     CMD [ "./app" ]
    
  1. docker-compose file - run the golang servers and nginx load balancer

     version: "3.8"
    
     services:
       rest_api:
         build:
           context: ./server
           dockerfile: Dockerfile
         environment:
           - PORT=:8000
         networks:
           - server-network
         command: /start
    
       nginx:
         image: nginx:latest
         volumes:
           - ./conf.d/nginx.conf:/etc/nginx/nginx.conf
         depends_on:
           - rest_api
         ports:
           - 8000:8000
         networks:
           - server-network
    
     networks:
       server-network:
         driver: bridge
    
  1. nginx conf file - We'll define events and set the expected maximum client concurrent connections to 1024. We can define a group of REST servers(image=rest_api) inside the upstream block. We can also mention the load balancing method inside the upstream block. NGINX server will listen on the port 8000 of the host. NGINX will proxy all the requests hitting at / route to app_servers group.

     events {
         worker_connections 1024;
     }
    
     http {
         upstream app_servers {
             # default load balancing method is Round Robin
             # other ex. least_conn, ip_hash, etc
             server rest_api:8000;
         }
    
         server {
             listen 8000;
    
             location / {
                 proxy_pass http://app_servers;
                 proxy_set_header Host $host;
                 proxy_set_header X-Real-IP $remote_addr;
                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             }
         }
     }
    

Now we can start multiple instances of golang REST API servers with the following command -

$ docker-compose up --build --scale rest_api=3

NGINX will serve the same request through different REST server instances -