Como funciona um Load Balance e como implementar utilizando Nginx.
Tags: nginx, programming, beginners, devops
Published: 2024-04-21 04:55:59

### O que é um Load Balance e para que serve?

Descrevendo de maneira mais técnica: o Load balance é uma técnica que distribui o tráfego entre servidores para otimizar o desempenho e a confiabilidade de uma rede ou sistema.

Dessa forma, é possível que, por exemplo, um site de comércio eletrônico distribua o tráfego entre vários servidores para lidar com um grande número de visitantes simultâneos, mantendo o site rápido e disponível.

O legal do Load Balance é a possibilidade de passar um "peso" para dizer qual servidor vai receber mais requisições de acordo com a configuração, vamos ver mais adiante. 

### Como implementar um Load Balance?

Para implementar um Load Balance, vamos utilizar um Software bem famoso estabilizado no mercado que permita que manipulemos um/o servidor HTTP, o `Nginx`.

> Nginx é um servidor leve de HTTP, proxy reverso, proxy de e-mail IMAP/POP3, feito por Igor Sysoev em 2005, sob licença BSD-like 2-clause. O Nginx consome menos memória que o Apache, pois lida com requisições Web do tipo “event-based web server”; e o Apache é baseado no “process-based server”, podendo trabalhar juntos.

Nesse post não estarei ensinando a instalar o Nginx, apenas como configurar um Load Balance.

### Arquitetura

Nosso desenho vai funcionar da seguinte forma:
- Toda vez que chegar uma requisição na porta 8000 (de acordo com a configuração)
- Vai ser redirecionado para o nosso servidor Nginx
- Quando chegar no Nginx, ele vai fazer o redirecionamento pelo Load Balance de acordo com os servidores configurados

![Architecture how works Nginx Load Balance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcg0rqd5vz7517a2rnoc.png)

### Implementação

Para este exemplo, estarei utilizando 2 aplicações em **Spring Boot Java**, mas você pode utilizar qualquer tecnologia que deseja ou framework.

Criei dois projetos no [Spring Initializr](https://start.spring.io/) só contendo a dependência do `Spring Web`.

Após a criação dos projetos, fiz uma controller em cada projeto bem simples:

#### Servidor 1:
```java
// imports

@RestController
@RequestMapping("/")
public class Server1Controller {

    @GetMapping()
    public ResponseEntity get() {
        return ResponseEntity.status(HttpStatus.OK).body("Olá, server 1");
    }
}
```

#### Servidor 2
```java
// imports

@RestController
@RequestMapping("/")
public class Server2Controller {

    @GetMapping()
    public ResponseEntity get() {
        return ResponseEntity.status(HttpStatus.OK).body("Olá, server 2");
    }
}
```

Não pode esquecer de trocar a porta da segunda ou primeira aplicação, vai da sua escolha:
```properties
server.port=8081
```

Após rodar as duas aplicações, vamos ter as seguintes respostas rodando o comando `curl`:


![Curl Request for two applications running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcabmw4s6a21yap8u7xj.png)

Boa, vemos que as duas aplicações estão rodando como desejado. Agora vamos para o Load Balance.

Para configurarmos o Load Balance, precisamos editar o arquivo de configuração do Nginx, o `nginx.conf`:

```nginx
http {
  upstream spring-project {
    server localhost:8080;
    server localhost:8081;
  }

  server {
    listen 8000;
    server_name 127.0.0.1;

    location / {
      proxy_pass http://spring-project;
    }
  }
}
```

Vou explicar o arquivo acima:

O bloco `http` é onde a configuração do servidor HTTP do Nginx é definida. Dentro desse bloco temos a definição de um grupo de servidores, chamado `spring-project` usando a diretiva `upstream`. Com isso, definimos um grupo de servidores que será usado para o balanceamento de carga, no caso temos 2 servidores:

```bash
127.0.0.1:8080
127.0.0.1:8081
```

Que por acaso, são nossos dois servidores que já estão rodando nossa aplicação Spring.

Mais abaixo há um bloco de `server`, que é a nossa configuração do servidor que vai ouvir na porta 8000 e responder requisições que venham do host `127.0.0.1`, dentro da localização padrão `/`. A partir disso o Nginx vai redirecionar todo o tráfego para os servidores dentro de spring-project, vamos ver?


![Implementation Load Balance Running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f9ztadakhmmgfg3ebvpg.png)

Olha que legal! De **quatro** requisições realizadas, ele balanceou todas as **quatro**, então **duas** foram para o **servidor 1** e duas foram para o **servidor 2**. Se eu quisesse modificar isso? Se eu quisesse que o servidor 1 recebesse três requisições a cada quatro?

É possível. Tem uma propriedade do `nginx`, chamado `weight`, que é o peso do balanceamento definido no servidor. Dessa forma, é possível influenciar ainda mais os algoritmos de balanceamento de carga nginx. Só alterar o arquivo `nginx.conf` dessa forma:

```nginx
server localhost:8080 weight=3;
```

**Obs: se o `weight` não é passado, o padrão é `1`**

Vamos ver como ficou após as alterações.


![Request Load Balancer With weight](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4htey9mmr4pe5dchfg8l.png)

Pronto. De cada quatro requisições, três caíram no servidor 1 e uma caiu no servidor 2.

Chegamos ao final. Espero que tenham gostado, deixarei aqui alguns links de referência.

[Using nginx as HTTP load balance](https://nginx.org/en/docs/http/load_balancing.html#:~:text=example.com%3B%20%7D-,Weighted%20load%20balancing,a%20particular%20load%20balancing%20method.)
[Simple Load Balancing](https://www.nginx.com/resources/wiki/start/topics/examples/loadbalanceexample/)
[Nginx](https://pt.wikipedia.org/wiki/Nginx)

Um abraço e bons estudos! Até mais!