고성능 웹 서버 분야에서 NGINX는 가볍고 효율적인 아키텍처로 많은 양의 트래픽을 처리할 수 있어 인기 있는 선택입니다. NGINX JavaScript 모듈(njs) 의 일부로 공유 사전 기능이 도입되면서 NGINX의 성능이 새로운 차원으로 도약했습니다.
이 블로그 게시물에서는 njs 공유 사전의 기능과 이점을 살펴보고 SSL/TLS 인증서를 순환할 때 재시작 없이 NGINX 오픈 소스를 설정하는 방법을 보여줍니다.
새로운 js_shared_dict_zone
지시어를 사용하면 NGINX 오픈 소스 사용자는 작업자 프로세스 간에 효율적인 데이터 교환을 위해 공유 메모리 영역을 활성화할 수 있습니다. 이러한 공유 메모리 영역은 키-값 사전 역할을 하여 실시간으로 액세스하고 수정할 수 있는 동적 구성 설정을 저장합니다.
공유 사전의 주요 이점은 다음과 같습니다.
evict
매개변수는 새로운 항목을 위한 공간을 만들기 위해 가장 오래된 키-값 쌍을 제거합니다.공유 사전의 가장 큰 영향력 있는 사용 사례 중 하나가 SSL/TLS 순환입니다. js_shared_dict_zone을
사용하면 SSL/TLS 인증서나 키가 업데이트되는 경우 NGINX를 다시 시작할 필요가 없습니다. 또한 NGINX에서 인증서를 관리할 수 있는 REST와 유사한 API를 제공합니다.
다음은 js_set
및 ssl_certificate
지시어로 HTTPS 서버를 설정하는 NGINX 구성 파일의 예입니다. 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 인증서나 키를 로드합니다. 또한, 캐시를 지속하고 업데이트하는 동안 요청에서 SSL/TLS 인증서나 키를 가져오는 js_content를
구현할 수도 있습니다.
이 예제의 전체 코드는 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 콘텐츠로 리디렉션됩니다."