link: Динамическое связывание приложений с Nginx
Требуется подписка Pro (или выше) на NGINX Extras от GetPageSpeed.
Установка
Вы можете установить этот модуль в любом дистрибутиве на основе RHEL, включая, но не ограничиваясь:
- RedHat Enterprise Linux 7, 8, 9 и 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 и Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-link
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-link
Включите модуль, добавив следующую строку в начало /etc/nginx/nginx.conf:
load_module modules/ngx_http_link_func_module.so;
В этом документе описывается nginx-module-link v3.2.6, выпущенный 12 августа 2026 года.
Нативные обработчики функций на C/C++ для NGINX — загружайте общие библиотеки и маршрутизируйте запросы напрямую в скомпилированный код с нулевыми издержками IPC.
Обзор
ngx_http_link_func связывает NGINX и нативные приложения на C/C++ через динамическое связывание. Общие библиотеки (файлы .so) загружаются при запуске сервера, а HTTP-запросы направляются напрямую в экспортируемые C-функции, работающие внутри рабочего процесса NGINX.
Это означает, что ваш C-код имеет прямой доступ к внутренним компонентам NGINX — заголовкам запросов, аргументам URI, телу запроса, общей памяти — и может записывать ответы без сериализации, сокетов или переключений контекста.
Возможности
- Диспетчеризация нативных функций — маршрутизация любого location на экспортируемую C-функцию
- Общая память и кэш — кэш на основе rbtree с блокировками мьютексов для всех рабочих процессов
- Разгрузка через пул потоков — поддержка потоков AIO для блокирующих операций
- Интеграция с подзапросами — объединение с
auth_requestдля потоков аутентификации - Удаленная загрузка библиотек — загрузка файлов
.soс HTTP/HTTPS URL при запуске - Хуки жизненного цикла — обратные вызовы инициализации и завершения для управления ресурсами
- Свойства на уровне сервера — передача значений конфигурации из
nginx.confв ваш код
Быстрый старт
nginx.conf:
http {
# Необязательно: общая память для кэша между рабочими процессами
ngx_link_func_shm_size 1m;
server {
listen 8080;
# Загрузка скомпилированного приложения
ngx_link_func_lib "/opt/myapp/libhandlers.so";
# Передача значений конфигурации в приложение
ngx_link_func_add_prop "db_host" "localhost:5432";
location /api/greeting {
ngx_link_func_call "handle_greeting";
}
location /api/users {
ngx_link_func_call "handle_users";
}
}
}
Ваше приложение (handlers.c):
#include <ngx_link_func_module.h>
void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle) {
ngx_link_func_cyc_log(info, cycle, "%s", "Приложение запущено");
}
void handle_greeting(ngx_link_func_ctx_t *ctx) {
ngx_link_func_write_resp(
ctx, 200, "200 OK",
ngx_link_func_content_type_json,
"{\"message\":\"Hello from C\"}", 25
);
}
void handle_users(ngx_link_func_ctx_t *ctx) {
const char *token = ngx_link_func_get_query_param(ctx, "token");
if (!token) {
ngx_link_func_write_resp(
ctx, 401, "401 Unauthorized",
ngx_link_func_content_type_plaintext,
"Missing token", 13
);
return;
}
// Обработка аутентифицированного запроса...
ngx_link_func_write_resp(
ctx, 200, "200 OK",
ngx_link_func_content_type_json,
"{\"users\":[]}", 12
);
}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle) {
ngx_link_func_cyc_log(info, cycle, "%s", "Приложение завершает работу");
}
Сборка и развертывание:
gcc -shared -o libhandlers.so -fPIC handlers.c
sudo cp libhandlers.so /opt/myapp/
sudo nginx -s reload
Директивы
ngx_link_func_shm_size
Контекст: main | По умолчанию: нет
Задает размер зоны общей памяти для кэша и обмена данными между рабочими процессами.
ngx_link_func_shm_size 10m;
ngx_link_func_lib
Контекст: server | По умолчанию: нет
Загружает общую библиотеку для блока server. Несколько блоков server могут загружать одну и ту же библиотеку для совместного использования памяти.
ngx_link_func_lib "/opt/myapp/libhandlers.so";
ngx_link_func_call
Контекст: location | По умолчанию: нет
Направляет запросы к экспортируемой C-функции по имени.
location /api/data {
ngx_link_func_call "handle_data";
}
ngx_link_func_add_prop
Контекст: server | По умолчанию: нет
Передает пары ключ-значение в приложение, доступные через ngx_link_func_get_prop().
ngx_link_func_add_prop "api_key" "secret123";
ngx_link_func_download_link_lib
Контекст: server | По умолчанию: нет
Загружает общую библиотеку с удаленного URL при запуске. Поддерживает дополнительные HTTP-заголовки для аутентификации.
# Базовая загрузка
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so" "/opt/myapp/libapp.so";
# С заголовками аутентификации
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so"
"Authorization:Bearer TOKEN\r\n"
"/opt/myapp/libapp.so";
ngx_link_func_ca_cert
Контекст: server | По умолчанию: нет
Задает сертификат CA для загрузки библиотек по HTTPS.
ngx_link_func_ca_cert "/etc/ssl/certs/ca-certificates.crt";
ngx_link_func_add_req_header
Контекст: location | По умолчанию: нет
Добавляет заголовок запроса, обычно используется для передачи переменных NGINX в подзапросы.
ngx_link_func_add_req_header "X-Real-IP" "$remote_addr";
ngx_link_func_subrequest
Контекст: location | По умолчанию: нет
Настраивает маршрутизацию подзапросов. Требуется NGINX, скомпилированный с --with-http_auth_request_module.
location /protected {
ngx_link_func_subrequest "/auth";
}
API приложения
Включите <ngx_link_func_module.h> в ваше приложение. Заголовочный файл предоставляет полный C API.
Хуки жизненного цикла
Эти зарезервированные имена функций вызываются автоматически NGINX:
void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle); // При запуске
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle); // При завершении/перезагрузке
Контекст запроса
Каждый обработчик получает ngx_link_func_ctx_t *ctx со следующими полями:
| Поле | Тип | Описание |
|---|---|---|
req_args |
char * |
Сырая строка запроса URI |
req_body |
u_char * |
Тело запроса |
req_body_len |
size_t |
Длина тела запроса |
shared_mem |
void * |
Указатель на общую память |
Функции
| Функция | Описание |
|---|---|
| Ответ | |
ngx_link_func_write_resp(ctx, status, status_line, content_type, body, len) |
Запись HTTP-ответа |
ngx_link_func_write_resp_l(ctx, status, status_line, sl_len, ct, ct_len, body, len) |
Запись ответа (с явными длинами) |
| Данные запроса | |
ngx_link_func_get_uri(ctx, &str) |
Получение URI запроса |
ngx_link_func_get_remote_addr(ctx) |
Получение удаленного адреса клиента |
ngx_link_func_get_header(ctx, key, keylen) |
Получение заголовка запроса по имени |
ngx_link_func_get_query_param(ctx, key) |
Получение параметра запроса по ключу |
ngx_link_func_get_prop(ctx, key, keylen) |
Получение свойства сервера |
| Заголовки | |
ngx_link_func_add_header_in(ctx, key, klen, val, vlen) |
Добавление входного заголовка |
ngx_link_func_add_header_out(ctx, key, klen, val, vlen) |
Добавление выходного заголовка |
| Память | |
ngx_link_func_palloc(ctx, size) |
Выделение из пула NGINX |
ngx_link_func_pcalloc(ctx, size) |
Выделение с обнулением из пула NGINX |
ngx_link_func_strdup(ctx, src) |
Дублирование строки из пула |
| Общая память | |
ngx_link_func_shm_alloc(shm, size) |
Выделение общей памяти |
ngx_link_func_shm_free(shm, ptr) |
Освобождение общей памяти |
ngx_link_func_shmtx_lock(shm) |
Захват мьютекса |
ngx_link_func_shmtx_unlock(shm) |
Освобождение мьютекса |
ngx_link_func_shmtx_trylock(shm) |
Попытка захвата мьютекса |
| Кэш | |
ngx_link_func_cache_get(shm, key) |
Получение кэшированного значения |
ngx_link_func_cache_put(shm, key, value) |
Сохранение кэшированного значения |
ngx_link_func_cache_new(shm, key, size) |
Выделение и кэширование |
ngx_link_func_cache_remove(shm, key) |
Удаление из кэша |
| Логирование | |
ngx_link_func_log_debug/info/warn/err(ctx, msg) |
Запись сообщения в журнал |
ngx_link_func_log(level, ctx, fmt, ...) |
Запись форматированного сообщения в журнал |
Константы типов контента
ngx_link_func_content_type_plaintext // "text/plain"
ngx_link_func_content_type_html // "text/html; charset=utf-8"
ngx_link_func_content_type_json // "application/json"
ngx_link_func_content_type_jsonp // "application/javascript"
ngx_link_func_content_type_xformencoded // "application/x-www-form-urlencoded"
Linux
gcc -shared -o libmyapp.so -fPIC myapp.c
macOS
clang -dynamiclib -o libmyapp.dylib -fPIC myapp.c -Wl,-undefined,dynamic_lookup ```