在web服务器领域中Nginx可以实现轻便高效的大流量处理。在Nginx JavaScript 模块(njs)中引入共享字典(shared dictionary)功能,可以大大加强Nginx的性能。本文华纳云整理了关于nginx开源版,如果是在没有重启的情况下,如何实现轮换。
通过共享字典可以轻松实现SSL轮换。使用js_shared_dict_zone不用重启Nginx就可以更新SSL/TLS证书或密钥。没有密钥的情况下,会在磁盘中读取证书或者密钥并放入缓存中。
另外还可以通过暴露一个位置,便于手动清除缓冲。当磁盘中文件更新,共享字典可以读取这些更新。
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 证书或密钥,同时持久化和更新缓存。如果想了解更多内容可以继续阅读华纳云新闻中心!