link:NGINX 应用程序动态链接
需要 GetPageSpeed NGINX Extras 订阅的 Pro 计划(或更高版本)。
安装
您可以在任何基于 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 发布于 2026 年 8 月 12 日。
NGINX 的原生 C/C++ 函数处理器 — 加载共享库并将请求直接路由到编译后的代码,零 IPC 开销。
概述
ngx_http_link_func 通过动态链接将 NGINX 与原生 C/C++ 应用程序桥接起来。共享库(.so 文件)在服务器启动时加载,HTTP 请求被直接分发到在 NGINX worker 进程内运行的导出 C 函数。
这意味着您的 C 代码可以直接访问 NGINX 内部结构 — 请求头、URI 参数、请求体、共享内存 — 并且无需序列化、套接字或上下文切换即可写入响应。
特性
- 原生函数分发 — 将任何 location 路由到导出的 C 函数
- 共享内存和缓存 — 基于 rbtree 的跨 worker 缓存,带互斥锁
- 线程池卸载 — 支持 AIO 线程处理阻塞操作
- 子请求集成 — 与
auth_request链式配合实现认证流程 - 远程库加载 — 启动时从 HTTP/HTTPS URL 获取
.so文件 - 生命周期钩子 — 用于资源管理的初始化和退出周期回调
- 每服务器属性 — 将
nginx.conf中的配置值传递给您的代码
快速开始
nginx.conf:
http {
# 可选:用于跨 worker 缓存的共享内存
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", "Application started");
}
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", "Application shutting down");
}
构建和部署:
gcc -shared -o libhandlers.so -fPIC handlers.c
sudo cp libhandlers.so /opt/myapp/
sudo nginx -s reload
指令
ngx_link_func_shm_size
上下文: main | 默认值: 无
设置用于跨 worker 缓存和数据共享的共享内存区域大小。
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 | 默认值: 无
为 HTTPS 库下载设置 CA 证书。
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 ```