AWS ELB (Elastic Load Balancing) に SSL 通信を復号させるとどれだけパフォーマンス変わるの?ってことでベンチマーク取った。
結果を誤解されると良くないので最初に言っておくと、 SSL の復号処理は ELB かどうかに関わらず重い 。ベンチマークを取ると平文の10分の1以下になるという話もある。
あと、秒間数十アクセス程度、または常にアクセス数が多い状況であれば、ELB に SSL 処理させるのが妥当。今回想定しているのは、スマホアプリにプッシュ通知して、ユーザが一斉にアクセスするような状況。しかも、ELB をウォームアップする余裕もないような。
今回の実験環境はこんな感じ。
叩く側のインスタンスA
↓
AWS ELB
↓
叩かれる側のインスタンスB
インスタンスはどちらも m1.small で Amazon Linux 2013.09.2 (ami-0d13700c)
インスタンスAには Apache Bench を入れる。
sudo yum install httpd-tools
インスタンスBには nodejs で簡単なサーバを立てる。
sudo yum install npm --enablerepo=epel
npm install express
cat <<EOT >index.js
var app = require('express')();
app.get('/*', function(req, res) {
if (req.query.wait) {
setTimeout(function() {
res.write('OK');
res.end();
}, req.query.wait);
} else {
res.write('OK');
res.end();
}
console.log('%s %s %s', new Date(), req.method, req.url);
});
app.listen(10080);
EOT
node index.js
ELB のセットアップ
- 443 (HTTPS) → 10080 (HTTP)
- 証明書は適切に設定
- 80 (HTTP) → 10080 (HTTP)
- 配下にインスタンスBを入れる
この設定で、インスタンスAから ab コマンドを打ってみた。まずは HTTP から。
$ ab -n 5000 -c 200 http://yourloadbalancer/?wait=200
(中略)
Document Path: /?wait=200
Document Length: 2 bytes
Concurrency Level: 200
Time taken for tests: 7.462 seconds
Complete requests: 5000
Failed requests: 0
Write errors: 0
Total transferred: 505286 bytes
HTML transferred: 10032 bytes
Requests per second: 670.07 [#/sec] (mean)
Time per request: 298.476 [ms] (mean)
Time per request: 1.492 [ms] (mean, across all concurrent requests)
Transfer rate: 66.13 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 2.4 1 22
Processing: 219 290 53.8 276 620
Waiting: 202 249 60.4 233 620
Total: 220 292 54.9 278 628
(後略)
だいたい毎秒 670 リクエスト。では次に HTTPS を。
$ ab -n 5000 -c 200 https://yourloadbalancer/?wait=200
(中略)
Server Port: 443
SSL/TLS Protocol: TLSv1,RC4-SHA,2048,128
Document Path: /?wait=200
Document Length: 2 bytes
Concurrency Level: 200
Time taken for tests: 104.943 seconds
Complete requests: 5000
Failed requests: 0
Write errors: 0
Total transferred: 594967 bytes
HTML transferred: 10002 bytes
Requests per second: 47.64 [#/sec] (mean)
Time per request: 4197.717 [ms] (mean)
Time per request: 20.989 [ms] (mean, across all concurrent requests)
Transfer rate: 5.54 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 96 2015 597.0 1993 4804
Processing: 504 2135 532.8 2112 4500
Waiting: 472 2122 534.9 2099 4500
Total: 1936 4150 516.0 4058 6810
(後略)
結果は HTTP の時の10分の1以下の毎秒 48 リクエスト。うーん、やっぱり重いんだな。何度か ab 叩いてみたけど、結果はそんなに変わらなかった。
DHE はむっちゃ重いよ という話を聞いたので、Cipher を DHE-RSA-AES256-SHA とか AES256-SHA とか RC4-SHA とかにして試してみたけど、どれも結果が秒間 50 リクエスト未満だった。
というわけで、ELB に SSL を復号させているシステムで、どうにもパフォーマンスが出ないといった場合はここを疑っておくといいんじゃないかと思った。対策としては、SSL の復号処理をバックエンドにやらせるとか、自前でロードバランサを組むとか。
なんか ELB 使えないみたいな流れになってしまったので補足しておくと、アクセス数が一定して多い場合は、ELB が自動でスケールするからパフォーマンスが出ないといったことにはならないと思う。
あと ELB には Pre-Warming というものがあって、事前に ELB をスケールさせておくことが出来る。これについては [AWSマイスターシリーズ]Amazon Elastic Load Balancing (ELB) の36ページに書かれているけどサポートに加入する必要がある。
あと最後に、 SSL の復号処理は ELB かどうかに関わらず根本的に重い
ブクマで ab -k をつけたら
ab で -k オプションつければ