Configure Nginx as a load balancer

NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability.

In this article, we will configure Nginx to act as a load balancer for 3 instances of an Spring boot application. This article will will configure load balancing using round robin algorithm to distribute load to the instances.

Pre-requisite installations

  1. Docker

Create a Spring Boot application

  1. Go to start.spring.io
  2. Add the Spring Web Dependency
  3. Select Maven
  4. Generate the project

Add an endpoint for testing

TestController.java

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController
{
    @GetMapping("/test")
    public ResponseEntity<String> testEndpoint()
    {
         System.out.println("Request Recieved");
         return new ResponseEntity<>("Success", HttpStatus.OK);
    }
}

Add the finalname tag in pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.umang345</groupId>
    <artifactId>nginx-load-balancer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nginx-load-balancer</name>
    <description>Configue nginx as load balancer</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <finalName>spring-server-instance</finalName>
    </build>

</project>

Add a Docker file to generate docker image for the spring boot application

Dockerfile

FROM openjdk:8
EXPOSE 8080
ADD target/spring-server-instance.jar spring-server-instance.jar
ENTRYPOINT ["java","-jar","/spring-server-instance.jar"]

Generate the jar files

Run the command

mvn clean install

to generate the jar files in the target directory.

Build the docker image for the Spring Boot project

Navigate to the project directory of the Spring Boot application and run

docker build -t spring-server-instance .

Run 3 instance of the spring boot application

Open 3 terminals and run the docker image for the spring application at port 8085, 8086, 8087.

docker run --name spring-server-instance1 -p8085:8080 spring-server-instance
docker run --name spring-server-instance2 -p8086:8080 spring-server-instance
docker run --name spring-server-instance3 -p8087:8080 spring-server-instance

Set up Nginx server

Pull the latest nginx image

docker pull nginx

Configure Nginx

Create a new directory for nginx and create a nginx.conf file in the directory.

nginx/ nginx.conf

http {
    upstream springserverinstance {
        server <ip address of instance 1>:8080;
        server <ip address of instance 1>:8080;
        server <ip address of instance 1>:8080;
    }

    server {
        listen 8080;
        location / {
            proxy_pass http://springserverinstance/;
        }
    }
}

Here Ip addresses of containers can be obtained by inspecting the containers individually

docker inspect spring-server-instance1
docker inspect spring-server-instance2
docker inspect spring-server-instance3

In this configuration file, we direct the traffic in round robin fashion to the three servers and expose port 8080 to listen to incoming requests.

Add the Docker file for nginx server

Create a Dockerfile in the same directory which contains nginx.conf file

nginx/ Dockerfile

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf

Create a docker image for our load balancer

Navigate to the nginx directory and run

docker build -f Dockerfile -t nginx-load-balancer

Run the load balancer as docker container

Open a terminal and run the docker image nginx-load-balancer created above

docker run --name nginx-load-balancer -p 8080:8080 nginx-load-balancer

We have finally placed a load balancer in front of our applications servers. To check the functionality, run

curl http://localhost:8080/test/?[1-100]

And in the console of the instances you can verify the load being evenly distributed across all three instances.

This article simulates functioning of load balancers at a basic level. The actual implementation in real world situations is far more complex than this.

I hope you found the article useful.

Lets connect :

Happy Coding :) .