Балансировка нагрузки с помощью Docker Compose + Nginx + Nestjs
Всем привет.
Возможно, вы сталкивались со случаями, когда ваш сервер перегружен, тормозит и не может обрабатывать входящие запросы.
И когда вы сталкиваетесь с этим случаем, есть несколько способов решения этой проблемы, например:
- Вариант 1. Определите основную причину кода, вызывающего ошибку.
- Вариант 2. Увеличение мощности сервера.
- Вариант 3. Используйте Docker + Nginx для создания балансировки нагрузки для распределения входящих запросов.
и т. д,...
Сегодня я расскажу, как реализовать Вариант 3. Технологии, которые я использую:
- NestJS
- Docker: Nginx, PM2
1. Создайте простой исходный код NestJs
Предварительные условия
Убедитесь, что Node.js (версия >= 16) установлен в вашей операционной системе.
Настройка
Настроить новый проект с помощью Nest CLI довольно просто. Установив npm, вы можете создать новый проект Nest с помощью следующих команд в терминале вашей ОС:
npm i -g @nestjs/cli
nest new load-balance-with-docker
Затем перейдите в папку с исходным кодом:
cd load-balance-with-docker
И у вас есть структура папки, как на картинке:
2. Конфигурация докера
Предварительные условия
Установите докер для вашего устройства: https://docs.docker.com/engine/install/
Нам нужно настроить 3 части:
- Nginx
- Server
- Pm2
2.1 Nginx
Создайте корневой каталог, создайте новую папку с именем nginx
:
Создайте файл с именем Dockerfile
в каталоге nginx
следующим образом:
# nginx/Dockerfile
FROM nginx:stable-alpine
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Приведенный выше фрагмент конфигурации представляет собой файл Dockerfile для создания образа Docker на основе образа nginx:stable-alpine
.
FROM nginx:stable-alpine
: эта строка определяет базовый образ, на котором будет основан новый образ, в данном случаеnginx:stable-alpine
. Изображениеnginx:stable-alpine
— это стабильная версия Nginx для Alpine Linux.
COPY default.conf /etc/nginx/conf.d/default.conf
: эта строка копирует файл default.conf в путь/etc/nginx/conf.d/default.conf
в образе. Файлdefault.conf
содержит конфигурацию Nginx, которая будет использоваться при запуске контейнера.
EXPOSE 80
: эта строка указывает, что контейнер будет прослушивать порт 80. Однако использованиеEXPOSE
не открывает порт на хост-компьютере, это просто инструкция, сообщающая другим, какой порт будет прослушивать контейнер.
CMD ["nginx", "-g", "daemon off;"]
: эта строка определяет команду, которую контейнер выполнит при запуске. В этом случае контейнер выполнит командуnginx -g 'daemon off;'
запустить Nginx в режиме без демона, чтобы контейнер не закрывался сразу после запуска Nginx.
Затем создайте файл default.conf
в каталоге nginx
.
# nginx/default.conf
upstream my-loadbalancer {
server my-loadbalancer:3000;
}
server {
listen 80;
location / {
proxy_pass http://my-loadbalancer/;
}
}
upstream my-loadbalancer { server my-loadbalancer:3000; }
: Этот фрагмент определяет группу серверов (восходящих) с именем «my-loadbalancer». В этом случае на порту 3000 работает только один внутренний сервер.
server { listen 80; ... }
: это конфигурация сервера Nginx. Он прослушивает порт 80 для обработки входящих HTTP-запросов.
location / { proxy_pass http://my-loadbalancer/; }
: В этом разделе определяется местоположение по умолчанию для всех запросов. Он используетproxy_pass
для перенаправления всех запросов на вышестоящий «бэкэнд». Это позволяет Nginx действовать как прокси-сервер и перенаправлять запросы на внутренний сервер, работающий на порту 3000.
2.2 Сервер
В основном каталоге создайте файл Dockerfile для сервера следующим образом:
# Use node:18 image
FROM node:18.0.0
# Set working directory
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm install
# Copy source code
COPY . .
# Build app
RUN npm run build
# Install PM2 globally
RUN npm install pm2 -g
# Set environment variables
ENV PORT 3000
# Expose port
EXPOSE $PORT
# Start app
CMD ["pm2-runtime", "start", "ecosystem.config.js"]
Затем создайте файл docker-compose.yml
:
version: '1'
services:
nginx:
build: ./nginx
ports:
- "80:80"
depends_on:
- my-loadbalancer
my-loadbalancer:
build: .
environment:
- PORT=3000
deploy:
replicas: 4
Приведенная выше конфигурация представляет собой файл, созданный докером, используемый для определения и запуска служб в среде Docker.
- Сначала он определяет две службы:
nginx
иmy-loadbalancer
.
- Служба
nginx
создается из каталога./nginx
и предоставляет порт80
на хосте и в контейнере.
- Перед запуском служба
nginx
также зависит от службыmy-loadbalancer
.
- Сервис
my-loadbalancer
создается из текущего каталога (каталога, содержащего файлdocker-compose
) и устанавливает переменную средыPORT=3000
.
- Наконец, сервис
my-loadbalancer
развертывается с четырьмя репликами для создания среды с балансировкой нагрузки. Вы можете изменить количество реплик на сервере.
2,3 м2
Создайте файл ecosystem.config.js
в корневом каталоге:
module.exports = {
apps: [{
name: 'my-loadbalancer',
script: 'dist/main.js',
instances: 'max',
autorestart: true,
watch: false,
max_memory_restart: '1G',
}]
};
3. Готово
Наконец, чтобы запустить сервер, вы можете использовать команду:
docker-compose up -d
Затем вы можете проверить контейнеры с помощью docker ps
:
Наконец, вы можете получить доступ к серверу по URL: http://localhost:80.
Вы можете проверить статистику контейнеров с помощью команды docker stats
.
Вы можете найти исходный код здесь.
Спасибо за чтение.