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

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

Директивы

Контекст: main | По умолчанию: нет

Задает размер зоны общей памяти для кэша и обмена данными между рабочими процессами.

ngx_link_func_shm_size 10m;

Контекст: server | По умолчанию: нет

Загружает общую библиотеку для блока server. Несколько блоков server могут загружать одну и ту же библиотеку для совместного использования памяти.

ngx_link_func_lib "/opt/myapp/libhandlers.so";

Контекст: location | По умолчанию: нет

Направляет запросы к экспортируемой C-функции по имени.

location /api/data {
    ngx_link_func_call "handle_data";
}

Контекст: server | По умолчанию: нет

Передает пары ключ-значение в приложение, доступные через ngx_link_func_get_prop().

ngx_link_func_add_prop "api_key" "secret123";

Контекст: 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";

Контекст: server | По умолчанию: нет

Задает сертификат CA для загрузки библиотек по HTTPS.

ngx_link_func_ca_cert "/etc/ssl/certs/ca-certificates.crt";

Контекст: location | По умолчанию: нет

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

ngx_link_func_add_req_header "X-Real-IP" "$remote_addr";

Контекст: 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 ```