在高性能 Web 服务器领域,NGINX 是一个广受欢迎的选择,因为其轻便高效的架构支持它处理大量流量。通过在 NGINX JavaScript 模块(njs)中引入共享字典(shared dictionary)功能,NGINX 的性能更上一层楼。
在本文中,我们将探讨 njs 共享字典的功能和优势,并展示如何设置 NGINX 开源版,以无需重启即可轮换 SSL/TLS 证书。
新 js_shared_dict_zone
指令允许 NGINX 开源版用户启用共享内存区,在 worker 进程之间高效交换数据。 这些共享内存区充当键值字典,存储着可实时访问和修改的动态配置设置。
共享字典的主要优势包括:
共享字典最有效的用例之一是 SSL/TLS 轮换。使用 js_shared_dict_zone
时,无需重启 NGINX 就可更新 SSL/TLS 证书或密钥。此外,它还提供了一个类似 REST 的 API,可用于管理 NGINX 上的证书。
下面是一个 NGINX 配置文件示例,该配置文件使用 js_set
和 ssl_certificate
指令来设置 HTTPS 服务器。 JavaScript 处理程序使用 js_set
从文件中读取 SSL/TLS 证书或密钥。
此配置片段使用共享字典将证书和密钥作为缓存存储在共享内存中。如果没有密钥,则会从磁盘中读取证书或密钥,并将其放入缓存。
您还可以暴露一个位置,以便手动清除缓存。一旦磁盘上的文件更新(如证书和密钥更新),共享字典就会从磁盘中读取这些更新。该调整允许在不重启 NGINX 进程的情况下轮换证书/密钥。
http { ...
js_shared_dict_zone zone=kv:1m;
server {
…
# 为变量设置一个 njs 函数。返回证书/密钥的值
js_set $dynamic_ssl_cert main.js_cert;
js_set $dynamic_ssl_key main.js_key;
# 使用变量的数据
ssl_certificate data:$dynamic_ssl_cert;
ssl_certificate_key data:$dynamic_ssl_key;
# 清除缓存的位置
location = /clear {
js_content main.clear_cache;
# 允许 127.0.0.1;
# 全部拒绝;
}
...
}
下面是使用 js_shared_dict_zone
轮换 SSL/TLS 证书和密钥的 JavaScript 实现:
function js_cert(r) { if (r.variables['ssl_server_name']) {
return read_cert_or_key(r, '.cert.pem');
} else {
return '';
}
}
function js_key(r) {
if (r.variables['ssl_server_name']) {
return read_cert_or_key(r, '.key.pem');
} else {
return '';
}
}
/**
* 从共享内存或磁盘读取密钥/证书值
*/
function read_cert_or_key(r, fileExtension) {
let data = '';
let path = '';
const zone = 'kv';
let certName = r.variables.ssl_server_name;
let prefix = '/etc/nginx/certs/';
path = prefix + certName + fileExtension;
r.log('Resolving ${path}');
const key = ['certs', path].join(':');
const cache = zone && ngx.shared && ngx.shared[zone];
if (cache) {
data = cache.get(key) || '';
if (data) {
r.log(`Read ${key} from cache`);
return data;
}
}
try {
data = fs.readFileSync(path, 'utf8');
r.log('Read from cache');
} catch (e) {
data = '';
r.log(`Error reading from file:${path}. Error=${e}`);
}
if (cache && data) {
try {
cache.set(key, data);
r.log('Persisted in cache');
} catch (e) {
const errMsg = `Error writing to shared dict zone: ${zone}. Error=${e}`;
r.log(errMsg);
}
}
return data
}
可通过发送 /clear
请求让缓存失效,这样 NGINX 在下一次 SSL/TLS 握手时就会从磁盘加载 SSL/TLS 证书或密钥。此外,您还可以使用 js_content
从请求中获取 SSL/TLS 证书或密钥,同时持久化和更新缓存。
本例的完整代码可在 njs GitHub 代码库中找到。
共享字典功能是一款强大的应用可编程性工具,在简化和可扩展性方面具有显著优势。利用 js_shared_dict_zone
的功能,您可以发掘新的增长机遇,并高效处理不断增长的流量需求。
准备好使用 js_shared_dict_zone
来加速 NGINX 部署了吗?您可以使用 js_shared_dict_zone
升级 NGINX 部署,解锁新的用例。有关此功能的更多信息,请参阅我们的文档。此外,您还可以在最近推出的 njs-acme 项目(支持 njs 模块运行时与 ACME 提供程序协同工作)中看到共享字典功能的完整示例。
如果您对 NGINX 开源版感兴趣或有任何问题,欢迎微信添加小 N 助手(微信号:nginxoss)加入 NGINX 官方微信群,以了解更多信息、提出问题并获得有关 NGINX 开源版的反馈。
"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."