WordPress
AWS
パフォーマンス
Lightsail

月5ドルで動かしているWordPressでTV東京のWBS砲をさばく

リフカムではRefcomeというサービスを運営しています。このサービスのホームページはWordPressで作られており、WordPressはAmazon Lightsailで構築しています。さらには、インスタンスのタイプも一番安い$5/monthなので大量のアクセスをさばくことは絶望的です。そこらへんは負荷が問題になってから考えればいいよねーと言って何も考えずに作ったのですが、TV取材が入って「放映されるから大至急高速化して」と言われて大慌てです。

実際に放送された内容

実際に放送された内容は以下になります。
http://www.tv-tokyo.co.jp/plus/business/entry/2018/017321.html
大体放映されたのが10分くらいで、撮影が1〜2時間くらいかかっているので編集の力を思い知ります。

Amazon Lightsailの性能を確かめる

さて、前述の通りWordPressをAmazon Lightsailで立ち上げており、インスタンスは一番安い5$/monthのプランです。
いくつかSEO用のプラグインやシェアボタン出すプラグインなどが有効化されていますが、それ以外に特殊なことはしていないです。この状態でabコマンドを叩いて性能を確認しましょう

$ ab -n 1000 -c 100 https://jp.refcome.com/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...[略]...

Document Path:          /
Document Length:        37314 bytes

Concurrency Level:      100
Time taken for tests:   61.214 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      37681000 bytes
HTML transferred:       37314000 bytes
Requests per second:    16.34 [#/sec] (mean)
Time per request:       6121.399 [ms] (mean)
Time per request:       61.214 [ms] (mean, across all concurrent requests)
Transfer rate:          601.13 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        8   29 108.2     16    1408
Processing:   382 5809 997.0   6056    7174
Waiting:      360 5771 996.7   6034    6451
Total:        392 5838 1004.0   6075    7300

Percentage of the requests served within a certain time (ms)
  50%   6075
  66%   6121
  75%   6150
  80%   6169
  90%   6276
  95%   6384
  98%   6484
  99%   6834
 100%   7300 (longest request)

だいたい16 requests per secondの性能があることが分かります。
以前他のスタートアップがWBSに取り上げられた際のWBS砲が、だいたい500 requests per secondだったそうです。
これを想定すると、30〜40倍に性能を上げる必要がありそうです。
今回は$5/monthの一番安いプランなので、ここは思い切って(思考放棄して)一番高いプランにスケールアップしてみます。

Lightsailのスケールアップ

インスタンスのスナップショットを作成して、そのスナップショットから新しいインスタンスを立ち上げるという流れです。
Lightsailのインスタンス一覧から、スナップショットを作りたいインスタンスの名前を調べ、その名前を指定してスナップショットを作ります。

$ aws lightsail --region ap-northeast-1 get-instances
$ aws lightsail --region ap-northeast-1 create-instance-snapshot \
      --instance-snapshot-name "jp-refcome-com-1-snapshot" \
      --instance-name "jp-refcome-com-1"

スナップショットの作成を確認して、完了したらそのスナップショットを元にインスタンスを作ります。
インスタンスのタイプは思い切って最高性能でお値段が$80/monthのものを選んでみましょう。

$ aws lightsail --region ap-northeast-1 get-instance-snapshots
$ aws lightsail --region ap-northeast-1 create-instances-from-snapshot \
      --instance-names "jp-refcome-com-2" \
      --availability-zone "ap-northeast-1a" \
      --instance-snapshot-name "jp-refcome-com-1-snapshot" \
      --bundle-id "large_1_0"

起動できたら、確認しましょう。

$ ab -n 1000 -c 100 https://jp.refcome.com/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...[略]...

Document Path:          /
Document Length:        37314 bytes

Concurrency Level:      100
Time taken for tests:   32.547 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      37681000 bytes
HTML transferred:       37314000 bytes
Requests per second:    30.72 [#/sec] (mean)
Time per request:       3254.697 [ms] (mean)
Time per request:       32.547 [ms] (mean, across all concurrent requests)
Transfer rate:          1130.61 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       21   85 235.0     35    2263
Processing:   429 3066 551.2   3179    4389
Waiting:      368 2965 540.2   3085    4055
Total:        459 3150 615.7   3227    6135

Percentage of the requests served within a certain time (ms)
  50%   3227
  66%   3323
  75%   3382
  80%   3427
  90%   3579
  95%   3801
  98%   4398
  99%   4575
 100%   6135 (longest request)

はい、30 requests per secondですね。うんちっちですね。うんちはトイレに流しましょう。
以下のコマンドでLightsailのインスタンスは削除できます。

$ aws lightsail --region ap-northeast-1 delete-instance \
      --instance-name "jp-refcome-com-2"

キャッシュにのせる

スケールアップではあまり性能が上がらなかったので、キャッシュを利用することにします。
CloudFrontを利用してGETリクエストをキャッシュするようにしてみました。

$ ab -n 1000 -c 100 https://jp.refcome.com/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...[略]...

Document Path:          /
Document Length:        37127 bytes

Concurrency Level:      100
Time taken for tests:   11.170 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      37675047 bytes
HTML transferred:       37127000 bytes
Requests per second:    89.53 [#/sec] (mean)
Time per request:       1116.962 [ms] (mean)
Time per request:       11.170 [ms] (mean, across all concurrent requests)
Transfer rate:          3293.94 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      151  613 312.7    608    3292
Processing:    90  449 219.3    437    1131
Waiting:       20  186 142.8    141     578
Total:        371 1062 396.1    955    4106

Percentage of the requests served within a certain time (ms)
  50%    955
  66%   1158
  75%   1350
  80%   1363
  90%   1517
  95%   1551
  98%   1971
  99%   2500
 100%   4106 (longest request)

90 requests per second...こちらもうんちっちですね。
しかし、CloudFrontをつかっているのにこんな結果になるのは何かおかしいです。
おもむろにオフィスの中を見渡し、、、発見してしまいました。
ボトルネック!!!!!!!!

9364983f-0ff0-4dbe-99eb-97e6666a8d92.jpg

会社のWiFiがうんちっちでした。AWSさん、すいませんでした:bow:
気持ちを改め、AWSにEC2を立ち上げ、そのEC2からabを実行してみます。

$ ab -n 1000 -c 100 https://jp.refcome.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking jp.refcome.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        jp.refcome.com
Server Port:            443

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   0.236 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      0 bytes
HTML transferred:       0 bytes
Requests per second:    4236.14 [#/sec] (mean)
Time per request:       23.606 [ms] (mean)
Time per request:       0.236 [ms] (mean, across all concurrent requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    12   22   3.7     22      63
Waiting:        0    0   0.0      0       0
Total:         12   22   3.7     22      63

Percentage of the requests served within a certain time (ms)
  50%     22
  66%     23
  75%     24
  80%     24
  90%     26
  95%     27
  98%     29
  99%     31
 100%     63 (longest request)

4200 requests per secondでした!これだけあればヤフー砲も安心ですね。

放送日当日

どきどきしながら、放送を待ちます。
番組にRefcomeというサービス名が出た瞬間に、GoogleAnalyticsのリアルタイムの訪問者数が跳ね上がります。

ピーク時
647.png

番組終了時
43.png

CloudFrontは元気にリクエストをさばいてくれました。
一方で秒単位のアクセス、つまりrequest per secですが、こちらはGoogleAnalyticsを見る限り多くても10を超えないくらいですね。あとでサーバのアクセスログも確認してみようと思います。
WBS砲がだいたい500 requests per secondということを聞いていたのでビクビクしていましたが、そこまで多くなかったですね。(これがC向けサービスだともっと激しかったのでしょうが。)
CloudFrontの力を借りましたが、実は全リクエストがLightsailのサーバに行っても問題なくリクエストさばけたかもしれません(謎)。

タイトルは盛っちゃいましたが、500円とCloudFront少しで無事にWBS砲を乗り切ることができました。