Перейти к содержанию

upstream-jdomain: Асинхронный модуль разрешения доменных имен для NGINX upstream

Установка на Debian/Ubuntu

Этот документ относится к пакету APT nginx-module-upstream-jdomain, предоставляемому репозиторием GetPageSpeed Extras.

  1. Настройте APT репозиторий, как описано в настройке APT репозитория.
  2. Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-upstream-jdomain
Показать дистрибутивы и архитектуры
| Дистрибутив | Версия            | Компонент   | Архитектуры    |
|-------------|-------------------|-------------|-----------------|
| debian      | bookworm          | main        | amd64, arm64    |
| debian      | bookworm-mainline | main        | amd64, arm64    |
| debian      | trixie            | main        | amd64, arm64    |
| debian      | trixie-mainline   | main        | amd64, arm64    |
| ubuntu      | focal             | main        | amd64, arm64    |
| ubuntu      | focal-mainline    | main        | amd64, arm64    |
| ubuntu      | jammy             | main        | amd64, arm64    |
| ubuntu      | jammy-mainline    | main        | amd64, arm64    |
| ubuntu      | noble             | main        | amd64, arm64    |
| ubuntu      | noble-mainline    | main        | amd64, arm64    |

Асинхронный модуль разрешения доменных имен для nginx upstream.

Этот модуль позволяет использовать доменное имя в блоке upstream и ожидать, что доменное имя будет динамически разрешено, чтобы ваш upstream мог быть устойчивым к обновлениям записей DNS.

Модуль не выполняет автоматическое разрешение DNS через определенные интервалы времени. Вместо этого разрешение DNS должно быть инициировано запросом для данного upstream. Если nginx обслуживает соединение, предназначенное для jdomain upstream, и прошел настроенный interval, тогда модуль выполнит запрос DNS.

Модуль совместим с другими директивами области upstream. Это означает, что вы можете заполнять блок upstream несколькими директивами jdomain, несколькими директивами server, keepalive, директивами балансировки нагрузки и т. д. Обратите внимание, что если в блоке upstream не указано иное средство балансировки нагрузки, этот модуль использует алгоритм балансировки нагрузки по умолчанию round robin, встроенный в ядро nginx.

Важно: Если указан альтернативный алгоритм балансировки нагрузки, он должен быть до директивы jdomain в блоке upstream! Если это не будет соблюдено, nginx сработает во время выполнения! Это происходит потому, что многие другие модули балансировки нагрузки явно расширяют встроенный round robin и поэтому в конечном итоге затрут обработчики инициализации jdomain, поскольку jdomain технически также является модулем балансировки нагрузки. Хотя это может не относиться ко всем модулям балансировки нагрузки, лучше оставаться на безопасной стороне и размещать jdomain после.

Важно: Из-за неблокирующего характера этого модуля и того, что его разрешение DNS инициируется входящими запросами, запрос, который инициирует поиск, на самом деле все равно будет перенаправлен на upstream, который был разрешен и кэширован до выполнения запроса DNS. В зависимости от сценария, это может привести к единичному сбою при изменении состояний upstream. Это важно помнить, чтобы обеспечить мягкие переходы ваших upstream.

Этот репозиторий является форком репозитория, исходно написанного wdaike. Поскольку данный проект больше не поддерживается, этот репозиторий стремится быть его преемником и сейчас имеет несколько функций впереди.

Использование

resolver 8.8.8.8; # Ваш локальный DNS-сервер

## Базовый upstream, использующий доменное имя с умолчанием на порт 80.
upstream backend_01 {
    jdomain example.com;
}

## Базовый upstream с указанием другого порта.
upstream backend_02 {
    jdomain example.com port=8080;
}

## Upstream с резервным сервером на случай, если хост не найден или
## ошибки формата при разрешении DNS.
upstream backend_03 {
    server 127.0.0.2 backup;
    jdomain example.com;
}

## Upstream, который будет использовать резервный сервер для любых и всех ошибок
## разрешения DNS.
upstream backend_04 {
    server 127.0.0.2 backup;
    jdomain example.com strict;
}

server {
    listen 127.0.0.2:80;
    return 502 'Ошибка.';
}

Синопсис

Синтаксис: jdomain <доменное-имя> [port=80] [max_ips=4] [interval=1] [strict]
Контекст: upstream
Атрибуты:
    port:       Порт, на котором слушает бэкенд.                                 (По умолчанию: 80)
    max_ips:    Размер буфера IP. Максимальное количество разрешенных IP для кэширования. (По умолчанию: 4)
    interval:   Сколько секунд для разрешения доменного имени.                       (По умолчанию: 1)
    ipver:      Будут использоваться только адреса семейства IPv4 или IPv6, если они указаны   (По умолчанию: 0)
    strict:     Требует, чтобы разрешение DNS прошло успешно и вернуло адреса,
                в противном случае помечает основной сервер и сопоставленные серверы как недоступные и
                принуждает использование других серверов в блоке upstream, если они есть. Ошибка разрешения может быть таймаутом, сбоем сервера DNS, отказом в подключении, ответом без
                адресов и т. д.

Смотрите https://www.nginx.com/resources/wiki/modules/domain_resolve/ для подробностей.

Разработка

Предварительные условия

Чтобы облегчить локальную разработку и позволить вам собирать и тестировать модуль, вам понадобятся некоторые инструменты.

  • Docker: для создания окружения, которое легко воспроизводит идеальные условия для сборки и тестирования.
  • act: для моделирования выполнения рабочих процессов github actions локально, чтобы избежать отправки коммитов только для наблюдения за тем, как CI не работает.
  • rust: зависимость cargo-make.
  • cargo-make: для выполнения общих задач разработки, таких как сборка, тестирование и форматирование кода.

Задачи

cargo-make - это усовершенствованный запускатель задач, который позволит вам легко выполнять общие операции разработки, такие как форматирование кода, сборка модуля, запуск тестирования и анализ кода. Вы можете увидеть определения задач в файле Makefile.toml. Установка cargo-make приведет к созданию отдельного исполняемого файла с именем makers, а также расширения cargo, которое можно выполнять с помощью cargo make. Поскольку этот проект не является rust-кратом, рекомендуется просто использовать makers.

Также обратите внимание, что ради простоты запускатель задач использует docker для выполнения всех задач. Это означает, что собираемый бинарник не предназначен для вашей хост-платформы.

Задача по умолчанию

Для добавления ценности, задача по умолчанию (т.е. простой запуск команды makers без аргументов) начнет интерактивную сессию bash внутри контейнера docker, используемого для этого проекта.

Это должно помочь с отладкой и общим рабочим процессом.

Форматирование

Неправильно отформатированный код приведет к сбою задачи линтинга в github actions. Чтобы избежать этого, вы можете запустить задачу форматирования перед отправкой новых изменений, вот так:

makers format

Это форматирование выполняется с помощью инструмента под названием clang-format. Вы можете найти варианты конфигурации для этого в файле ./.clang-format.

Статический анализ кода

Вы можете запустить статический анализ кода с помощью задачи анализа:

makers analyse

Этот анализ производится с помощью инструмента под названием clang-tidy. Вы можете найти варианты конфигурации для этого в файле ./.clang-tidy.

Тестирование

Вы можете запустить пакет тестов с помощью задачи тестирования, вот так:

makers test

Отладка

Мы можем использовать valgrind и gdb на nginx изнутри контейнера.

Сначала откройте интерактивную оболочку в контейнере с помощью:

$ makers

Мы будем использовать эту сессию для запуска valgrind:

$ valgrind --vgdb=full --vgdb-error=0 /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf
==15== Memcheck, детектор ошибок в памяти
==15== Copyright (C) 2002-2017, и GNU GPL, авторы: Julian Seward et al.
==15== Используя Valgrind-3.13.0 и LibVEX; повторный запуск с -h для справки о копирайте
==15== Команда: /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf
==15==
==15== (действие при запуске) vgdb me ...
==15==
==15== ДЛЯ ОТЛАДКИ ЭТОГО ПРОЦЕССА С ПОМОЩЬЮ GDB: запустите GDB так
==15==   /path/to/gdb /github/workspace/bin/static/nginx
==15== и затем дайте GDB следующую команду
==15==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15
==15== --pid является необязательным, если только один процесс valgrind работает
==15==

Затем найдите идентификатор контейнера, чтобы мы могли открыть еще одну сессию внутри него:

$ docker ps
CONTAINER ID        IMAGE                                     COMMAND             CREATED             STATUS              PORTS                    NAMES
55fab1e069ba        act-github-actions-nginx-module-toolbox   "bash"              4 seconds ago       Up 3 seconds        0.0.0.0:1984->1984/tcp   serene_newton

Используйте либо имя, либо ID, чтобы выполнить bash-сессию внутри контейнера:

$ docker exec -it serene_newton bash

Мы будем использовать эту сессию для запуска gdb и нацеливания на сервер gdb valgrind, который мы запустили в другой сессии:

$ gdb /github/workspace/bin/static/nginx
GNU gdb (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3
Copyright (C) 2017 Free Software Foundation, Inc.
Лицензия GPLv3+: GNU GPL версия 3 или более поздняя <http://gnu.org/licenses/gpl.html>
Это бесплатное программное обеспечение: вы можете изменять и распространять его.
Гарантии нет, в той мере, в которой это допускается законом. Введите "show copying"
и "show warranty" для подробностей.
Этот GDB был настроен как "x86_64-redhat-linux-gnu".
Введите "show configuration" для получения подробностей о конфигурации.
Для инструкций по отчетности о ошибках, пожалуйста, смотрите:
<http://www.gnu.org/software/gdb/bugs/>.
Найдите руководство GDB и другие документационные ресурсы онлайн на:
<http://www.gnu.org/software/gdb/documentation/>.
Для получения помощи введите "help".
Введите "apropos слово", чтобы найти команды, связанные со словом...
Чтение символов из /github/workspace/bin/static/nginx...готово.
(gdb)

Из запроса gdb нацелитесь на процесс valgrind и начните отладку:

(gdb) target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15
Удаленная отладка с использованием | /usr/lib64/valgrind/../../bin/vgdb --pid=15
пересылает данные между gdb и процессом 15
предупреждение: удаленная цель не поддерживает передачу файлов, пытается получить доступ к файлам из локальной файловой системы.
Чтение символов из /lib64/ld-linux-x86-64.so.2...(нет отладочных символов)...готово.
0x0000000004000ef0 in _start () from /lib64/ld-linux-x86-64.so.2
Отсутствует отдельная информация об отладке, используйте: debuginfo-install glibc-2.26-35.amzn2.x86_64
(gdb)

Запуск GitHub Actions

С помощью act вы можете смоделировать рабочий процесс, который будет запускаться на серверах GitHub после того, как вы внесли изменения.

В основном рабочем процессе более одной задачи, поэтому вам нужно указать тестовую задачу при запуске act. Например, вы можете использовать эту команду для проверки форматирования кода:

act -vj lint

Обратите внимание, что задача lint не форматирует ваш код, она только проверяет, что форматирование выполнено как ожидалось.

Также обратите внимание, что -v используется для включения режима подробного отображения, чтобы предоставить больше информации о том, что делает act.

Задачи, которые вы можете (и должны) запускать локально, это lint, build, analyse и test. Задача test зависит от результата задачи build. Чтобы сохранить вывод из задачи сборки, вы можете добавить флаг -b к act, или вы просто можете использовать запускатель задач для сборки.

Известные проблемы

На данный момент? Никаких! 🎉

Если вы обнаружите ошибку или у вас есть вопрос, пожалуйста, откройте задачу.

Исходный автор

wdaike wdaike@163.com (https://github.com/wdaike), Baidu Inc.