Layer 7 Load Balancing Using Nginx

Layer 7 Load Balancing Using Nginx

·

6 min read

Layer 7 load balancing operates at the application layer of the OSI model, which is the highest layer. Unlike Layer 4 load balancing ( Previously Discussed ), which relies on IP addresses and ports, Layer 7 load balancers make routing decisions based on the content of the HTTP/HTTPS requests. This means that the load balancer can inspect and analyze elements such as HTTP headers, URLs, cookies, and even the content of the message body itself.

Features

  • Content-Based Routing: Layer 7 load balancers can direct traffic based on specific content within the request, such as URL paths, hostnames, or HTTP methods.

    For example, requests to /frontend can be routed to one set of servers, while

    requests to /backend can be routed to another. We will deep dive into the project.

  • SSL Termination: Layer 7 load balancers can handle SSL/TLS decryption, which offloads the computational burden from backend servers. By terminating SSL at the load balancer, it decrypts the incoming encrypted traffic and forwards it to the backend servers in plaintext. This improves performance and simplifies the management of SSL certificates, as they only need to be maintained on the load balancer. [ Will be discussed deeply into next blog ]

  • Application-Aware Routing: This feature allows Layer 7 load balancers to make routing decisions based on application-specific data, such as user sessions, cookies, or even the contents of a POST request. For instance, a load balancer might direct all traffic from a particular user to a specific server to maintain session persistence, or it might route requests differently based on a user’s authentication status.

  • Traffic Shaping and Rate Limiting: Layer 7 load balancers can implement traffic shaping policies, such as limiting the number of requests to a particular backend based on defined thresholds. This can be used to prevent overloading specific servers or to enforce quotas on API usage.

  • Security Features: With the ability to inspect the content of requests, Layer 7 load balancers can provide security features such as Web Application Firewall (WAF) integration, which protects against common web exploits like SQL injection and cross-site scripting (XSS).

  • Compression and Caching: Layer 7 load balancers can compress content before delivering it to the client, reducing bandwidth usage and improving load times. They can also cache responses from backend servers, reducing the need to process identical requests multiple times.

Key Differences Between L4 and L7 Load Balancing

AspectLayer 4 Load BalancingLayer 7 Load Balancing
Routing LogicBased on IP addresses and ports.Based on application-level data, such as HTTP headers or request content.
Performance and OverheadGenerally faster and more efficient, with less overhead.Can introduce more overhead due to the need for deep packet inspection.
Flexibility and ControlLimited control, suitable for straightforward routing.Offers fine-grained control, enabling more sophisticated routing decisions.
SSL/TLSNot capable of providing SSL features.Can handle SSL termination, preventing man-in-the-middle attacks.
ScalabilityEasier to scale due to lower resource consumption.May require more resources but provides scalability through smarter routing and distribution of traffic.

Deep Dive: Layer 7 Load Balancing Project

Project Overview

For this project, we've created a Docker Compose setup that includes:

  • NGINX Load Balancer: Configured as a Layer 7 load balancer, NGINX listens for incoming HTTP requests and routes them to different Flask application instances based on the URL paths specified by the client.

  • Flask Applications: Four instances of a simple Flask-based Python app running in Docker containers, designed to simulate a typical web service..

Project :- [Link]

Here's how it is working:

  • / (Root URL): When a client sends a request to the root URL (/), NGINX forwards this request to the home_page upstream group. This group includes all four Flask application instances (app1:5000, app2:5000, app3:5000, app4:5000). NGINX will load balance the requests across these instances, returning the response from one of the apps.

  • /frontend: Requests made to /frontend are proxied by NGINX to the lb-set-1 upstream group, which consists of app1:5000 and app2:5000. These two instances handle the traffic for this path, with NGINX distributing the load between them.

  • /backend: Requests directed to /backend are routed by NGINX to the lb-set-2 upstream group, which includes app3:5000 and app4:5000. These instances manage the backend traffic, with NGINX balancing the load between them.

  • /admin: If a client attempts to access the /admin path, NGINX is configured to block the request by returning a 403 Forbidden status. This ensures that the admin area is inaccessible, providing an additional layer of security.

This setup demonstrates the power of Layer 7 load balancing, where NGINX can inspect and route traffic based on the specific URL paths, providing granular control over how traffic is distributed across backend services.

NGINX Configuration

Here’s the NGINX configuration (nginx.conf) that used in my project.

# nginx layer 7 proxy 
events { }

http {
    upstream home_page {
        server app1:5000;
        server app2:5000;
        server app3:5000;
        server app4:5000;
    }
    upstream lb-set-1 {
        server app1:5000;
        server app2:5000;
    }
    upstream lb-set-2 { 
        server app3:5000;
        server app4:5000;
    }

    server {
        listen 80;

        # Default request handler (for `/`)
        location / { 
            proxy_pass http://home_page;  # Requests to `/` will be load-balanced by `home_page`
        }

        # Handling `/frontend` requests
        location /frontend {
            proxy_pass http://lb-set-1;  # Requests to `/frontend` will be load-balanced by `lb-set-1`
        }

        # Handling `/backend` requests
        location /backend {
            proxy_pass http://lb-set-2;  # Requests to `/backend` will be load-balanced by `lb-set-2`
        }

        # Block access to `/admin`
        location /admin {
            return 403;  # Returns a 403 Forbidden status for `/admin` requests
        }
    }
}

Run the Project Locally

  1. Clone the Project: Begin by cloning the project repository to your local machine. You can do this using the following command:

     git clone https://github.com/sakib3001/nginx-layer-7-load-balancer
    
  2. Navigate to the Directory: Change into the project directory where the docker-compose.yml file is located:

     cd nginx-layer-7-load-balancer
    
  3. Deploy the Containers: Use Docker Compose to build and deploy the containers. Run the following command:

     docker compose up -d --build
    
  4. Verify the Containers: After the containers are up and running, verify their status using:

     docker ps
    

    Ensure that all the containers (nginx, app1, app2, app3, and app4) are running without any issues.

Test the Load Balancing

  • Open your web browser and navigate to http://localhost. This should direct you to one of the Flask application instances via the home_page group.

    then refresh the page and you will able to see the app3 will be changed any of

    app1 app2 app4

  • Next, navigate to http://localhost/frontend. This request will be routed to either app1 or app2, handled by the lb-set-1 group.

  • Then, navigate to http://localhost/backend. This request will be handled by either app3 or app4, managed by the lb-set-2 group.

  • Finally, try accessing http://localhost/admin. You should see a 403 Forbidden response, as NGINX is configured to block access to this path.

    To Be Continued...

    Note: In the next blog, we will dive deeply into SSL/TLS concepts. We'll explore how these protocols work, their importance in securing web traffic, and then implement SSL/TLS certificates into our Layer 7 load balancer setup.