在高性能 Web 服务器领域, NGINX是一个受欢迎的选择,因为其轻量级、高效的架构使其能够处理大量流量。 随着NGINX JavaScript 模块(njs)中共享字典功能的引入,NGINX 的性能能力达到了一个新的水平。
在这篇博文中,我们探讨了 njs 共享字典的功能和优势,并展示了如何设置 NGINX 开源,而无需在轮换 SSL/TLS 证书时重新启动。
新的js_shared_dict_zone
指令允许 NGINX 开源用户启用共享内存区域,以便在工作进程之间实现高效的数据交换。 这些共享内存区域充当键值字典,存储可实时访问和修改的动态配置设置。
共享词典的主要优点包括:
evict
参数删除最旧的键值对,为新条目腾出空间。共享字典最有影响力的用例之一是 SSL/TLS 轮换。 使用js_shared_dict_zone
时,如果发生 SSL/TLS 证书或密钥更新,则无需重新启动 NGINX。 此外,它还为您提供了类似 REST 的 API 来管理 NGINX 上的证书。
下面是 NGINX 配置文件的示例,它使用js_set
和ssl_certificate
指令设置 HTTPS 服务器。 JavaScript 处理程序使用js_set
从文件中读取 SSL/TLS 证书或密钥。
此配置片段使用共享字典将证书和密钥存储在共享内存中作为缓存。 如果密钥不存在,那么它会从磁盘读取证书或密钥并将其放入缓存中。
您还可以显示清除缓存的位置。 一旦磁盘上的文件更新(例如,证书和密钥被更新),共享字典就会强制从磁盘读取。 此调整允许轮换证书/密钥,而无需重新启动 NGINX 进程。
http { ...
js_shared_dict_zone zone=kv:1m;
server {
…
# Sets an njs function for the variable. Returns a value of cert/key
js_set $dynamic_ssl_cert main.js_cert;
js_set $dynamic_ssl_key main.js_key;
# use variable's data
ssl_certificate data:$dynamic_ssl_cert;
ssl_certificate_key data:$dynamic_ssl_key;
# a location to clear cache
location = /clear {
js_content main.clear_cache;
# allow 127.0.0.1;
# deny all;
}
...
}
以下是使用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 '';
}
}
/**
* Retrieves the key/cert value from Shared memory or fallback to disk
*/
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 repo中找到。
共享字典功能是您的应用程序可编程性的强大工具,在精简和可扩展性方面带来了显著的优势。 通过利用js_shared_dict_zone
的功能,您可以释放新的增长机会并有效处理不断增长的流量需求。
准备好使用js_shared_dict_zone
增强你的 NGINX 部署了吗? 您可以使用js_shared_dict_zone
升级您的 NGINX 部署以解锁新的用例,并在我们的文档中了解有关此功能的更多信息。 此外,您还可以在最近推出的njs-acme 项目中看到共享字典功能的完整示例,这使得 njs 模块运行时能够与 ACME 提供程序一起工作。
如果您有兴趣开始使用 NGINX 开源并且有疑问,请加入 NGINX 社区 Slack – 介绍自己并了解这个 NGINX 用户社区!
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”