인터넷을 탐색할 때 SSL을 통한 암호화가 매우 중요하다는 것은 모두가 알고 있는 사실입니다. PayPal에서는 보안을 최우선으로 생각합니다. 우리는 공개 웹사이트뿐만 아니라 내부 서비스 호출에도 엔드투엔드 암호화를 사용합니다. SSL 암호화 기술은 node.js의 성능에 큰 영향을 미칩니다. 우리는 외부 서비스를 조정하고 최대한 활용하는 데 시간을 투자했습니다. 다음은 SSL 외부 성능을 크게 향상시키는 것으로 밝혀진 일부 SSL 구성 조정 목록입니다.
SSL 비밀번호
기본적으로 Node.js용 SSL은 매우 강력한 암호화 알고리즘 세트를 사용합니다. 특히 Diffie-Hellman 키 교환 및 타원 곡선 알고리즘은 비용이 매우 많이 듭니다. 그리고 기본 구성에서 아웃바운드 SSL 호출을 너무 많이 사용하면 Node.js의 성능이 근본적으로 약화됩니다. 얼마나 느린지 파악하기 위해 서비스 호출의 CPU 샘플을 살펴보겠습니다.
918834.0ms 100.0% 0.0 node (91770) 911376.0ms 99.1% 0.0 start 911376.0ms 99.1% 0.0 node::Start 911363.0ms 99.1% 48.0 uv_run 909839.0ms 99.0% 438.0 uv__io_poll 876570.0ms 95.4% 849.0 uv__stream_io 873590.0ms 95.0% 32.0 node::StreamWrap::OnReadCommon 873373.0ms 95.0% 7.0 node::MakeCallback 873265.0ms 95.0% 15.0 node::MakeDomainCallback 873125.0ms 95.0% 61.0 v8::Function::Call 873049.0ms 95.0% 13364.0 _ZN2v88internalL6InvokeEbNS0 832660.0ms 90.6% 431.0 _ZN2v88internalL21Builtin 821687.0ms 89.4% 39.0 node::crypto::Connection::ClearOut 813884.0ms 88.5% 37.0 ssl23_connect 813562.0ms 88.5% 54.0 ssl3_connect 802651.0ms 87.3% 35.0 ssl3_send_client_key_exchange 417323.0ms 45.4% 7.0 EC_KEY_generate_key 383185.0ms 41.7% 12.0 ecdh_compute_key 1545.0ms 0.1% 4.0 tls1_generate_master_secret 123.0ms 0.0% 4.0 ssl3_do_write ...
키 생성에 집중해보자:
802651.0ms 87.3% 35.0 ssl3_send_client_key_exchange 417323.0ms 45.4% 7.0 EC_KEY_generate_key 383185.0ms 41.7% 12.0 ecdh_compute_key
이 호출 시간의 87%가 키 생성에 사용되었습니다!
이러한 비밀번호는 계산 집약도를 낮추기 위해 변경할 수 있습니다. 이 아이디어는 https(또는 프록시)를 통해 구현되었습니다. 예:
var agent = new https.Agent({ "key": key, "cert": cert, "ciphers": "AES256-GCM-SHA384" });
위 키는 고가의 Diffie-Hellman 키로 교환되지 않았습니다. 비슷한 것으로 교체한 후 아래 예에서 중요한 변화를 확인할 수 있습니다.
... 57945.0ms 32.5% 16.0 ssl3_send_client_key_exchange 28958.0ms 16.2% 9.0 generate_key 26827.0ms 15.0% 2.0 compute_key ...
OpenSSL 문서를 통해 암호 문자열에 대해 자세히 알아볼 수 있습니다.
SSL 세션 재개
서버가 SSL 세션 재개를 지원하는 경우 https(또는 프록시)를 통해 세션을 전달할 수 있습니다. 프록시의 createConnection 함수를 래핑할 수도 있습니다.
var createConnection = agent.createConnection; agent.createConnection = function (options) { options.session = session; return createConnection.call(agent, options); };
세션 재개는 연결에 짧은 핸드셰이크 메커니즘을 추가하여 사용되는 연결 수를 줄일 수 있습니다.
계속 활동하세요
프록시가 활성 상태로 유지되도록 허용하면 SSL 핸드셰이크가 쉬워집니다. Agentkeepalive와 같은 연결 유지 에이전트는 노드 연결 유지 문제를 해결할 수 있지만 Node 0.12에서는 필요하지 않습니다.
유념해야 할 또 다른 사항은 프록시의 maxSockets입니다. 값이 높으면 성능에 부정적인 영향을 미칠 수 있습니다. 생성한 아웃바운드 연결 수에 따라 maxSockets 값을 제어하세요.
슬래브 크기
tls.SLAB_BUFFER_SIZE는 tls 클라이언트(서버)가 사용하는 슬랩 버퍼의 할당 크기를 결정합니다. 크기는 기본적으로 10MB입니다.
이 할당된 범위는 RSS를 확장하고 가비지 수집 시간을 증가시킵니다. 이는 높은 용량이 성능에 영향을 미친다는 것을 의미합니다. 이 용량을 더 낮은 값으로 조정하면 메모리 및 가비지 수집 성능이 향상될 수 있습니다. 버전 0.12에서는 슬래브 할당이 개선되어 추가 조정이 필요하지 않습니다.
0.12 SSL의 최근 변경 사항
Fedor의 SSL 강화 버전을 테스트해 보세요.
테스트 지침
http 서비스를 SSL 서비스 프록시로 실행하세요. 모두 이 컴퓨터에서 실행됩니다.
v0.10.22
Running 10s test @ http://127.0.0.1:3000/ 20 threads and 20 connections Thread Stats Avg Stdev Max +/- Stdev Latency 69.38ms 30.43ms 268.56ms 95.24% Req/Sec 14.95 4.16 20.00 58.65% 3055 requests in 10.01s, 337.12KB read Requests/sec: 305.28 Transfer/sec: 33.69KB
v0.11.10-pre(메인 버전에서 빌드)
Running 10s test @ http://127.0.0.1:3000/ 20 threads and 20 connections Thread Stats Avg Stdev Max +/- Stdev Latency 75.87ms 7.10ms 102.87ms 71.55% Req/Sec 12.77 2.43 19.00 64.17% 2620 requests in 10.01s, 276.33KB read Requests/sec: 261.86 Transfer/sec: 27.62KB
큰 차이는 없지만 기본 비밀번호 때문이므로 비밀번호의 프록시 옵션을 조정해 보겠습니다. 예:
var agent = new https.Agent({ "key": key, "cert": cert, "ciphers": "AES256-GCM-SHA384" });
v0.10.22
Running 10s test @ http://localhost:3000/ 20 threads and 20 connections Thread Stats Avg Stdev Max +/- Stdev Latency 59.85ms 6.77ms 95.71ms 77.29% Req/Sec 16.39 2.36 22.00 61.97% 3339 requests in 10.00s, 368.46KB read Requests/sec: 333.79 Transfer/sec: 36.83KB
v0.11.10-pre(메인 버전에서 빌드)
Running 10s test @ http://localhost:3000/ 20 threads and 20 connections Thread Stats Avg Stdev Max +/- Stdev Latency 38.99ms 5.96ms 71.87ms 86.22% Req/Sec 25.43 5.70 35.00 63.36% 5160 requests in 10.00s, 569.41KB read Requests/sec: 515.80 Transfer/sec: 56.92KB
보시다시피 Fedor의 수정 후에는 큰 차이가 있습니다. 0.10에서 0.12까지의 성능 차이는 거의 2배입니다!
요약
어떤 사람들은 "SSL을 그냥 끄면 안 되나, 끄고 나면 더 빨라지잖아"라고 물을 수도 있고, 어떤 사람들에게는 이것이 선택 사항이기도 합니다. 실제로 이것이 사람들에게 SSL 성능 문제를 어떻게 해결하는지 물을 때 나오는 일반적인 대답입니다. 그러나 기업의 SSL 요구 사항이 전혀 증가하지 않고 Node.js에서 SSL을 개선하기 위해 많은 노력을 기울인 경우에도 여전히 성능 조정이 필요합니다. 위 기술 중 일부가 SSL 사용 사례의 성능을 조정하는 데 도움이 되기를 바랍니다.