Amazon EC2 + Amazon CloudFront のパフォーマンスを測る

実際、EC2 単体と CloudFront 利用時とでは、どのくらいアプリケーションのパフォーマンスが異なるのだろうか。Amazon CloudFront の性能測定を行ってみた。



<p>結論から言えば、画像などの静的コンテンツを多用したサイトであれば、劇的に速くなる。</p>

<p>国内にサーバを置いてあるウェブアプリケーションを EC2 で試しに動かしたところ、遅くて使い物にならなかった。EC2 での動的リクエスト処理は許容範囲であったが、多量の画像や css、js などを返す処理が遅かった。Keep-Alive は Off にしているので、その潜在力を活かしきったというわけではないが、このアプリは Keep-Alive Off で動かしたかった。</p>

<p>それを CloudFront 併用で動かしたところ、速度が数倍に向上し、体感速度は問題ないレベルに達した。画像が多くて EC2 には移行できないと考えている人には、一度使ってみることをお勧めしたい。</p>

<p>具体的な数値は以下に載せるが、ブラウザキャッシュを活かした状態で、コンテンツを全て返し終わるまでにEC2単体で 10~15秒かかっていたものが、CloudFront 併用時には 2~4秒にまで縮まった。そのうちの0.5秒程度は Google Analytics 待ちなので、画面が完全に表示されるまでの時間はおよそ3秒以内に収まっている。</p>

<blockquote><pre>
□ ページ1 (リクエスト:31回, 転送量:386KB)

1回目 2回目 3回目 平均
———————————————
EC2単体
キャッシュ無し 17.07s 16.81s 17.02s 17.0s
キャッシュ有り 10.72s 16.44s 6.93s 11.4s
EC2 + CloudFront
キャッシュ無し 4.16s 3.18s 3.12s 3.49s
キャッシュ有り 2.3s 2.4s 1.82s 2.17s

□ ページ2 (リクエスト:77回, 転送量:518KB)

1回目 2回目 3回目 平均
———————————————
EC2単体
キャッシュ無し 20.6s 25.03s 26.61s 24.08s
キャッシュ有り 13.26s 12.97s 13.31s 13.18s
EC2 + CloudFront
キャッシュ無し 3.89s 4.76s 4.09s 4.25s
キャッシュ有り 4.34s 3.74s 3.31s 3.80s

□ ページ3 (リクエスト:96回, 転送量: 621KB)

1回目 2回目 3回目 平均
———————————————
EC2単体
キャッシュ無し 24.63s 24.19s 22.28s 23.7s
キャッシュ有り 15.65s 14.85s 14.78s 15.09s
EC2 + CloudFront
キャッシュ無し 5s 4.06s 4.35s 4.47s
キャッシュ有り 4.03s 3.13s 2.99s 3.38s
</pre></blockquote>

<h4>その他いろいろ</h4>
<p>まず、CloudFront の現在のバージョンでは、SSL がサポートされていない。https ではアクセスができないので注意が必要。</p>

<p>S3 でファイルを更新したときに CloudFront に反映される時間は、CloudFront のキャッシュが切れるまで。キャッシュが切れれば再度 S3 から最新のコンテンツを取得する。キャッシュはデフォルトでは24時間保持される。FAQ によれば、自動的にキャッシュが切れるのを待たずにキャッシュを消したい場合は、有害コンテンツ系のものであれば Amazon が個別対応してくれるようだ。</p>

Amazon CloudFront を cfcurl.pl から使う

Amazon EC2 は安くて性能もよい素晴らしいサービスだが、EC2 で画像の多いウェブアプリを作ると画面が表示されるまでにやや時間がかかる。国内に置いたサーバの方に、ユーザエクスペリエンスでは分がある。Amazon CloudFront という CDN(Contents Delivery Network) サービスを使えば、この遅さを解消できるのではないかと期待して試してみた。



<p>
手順は次のとおり。
<ol>
<li>アカウントの設定で Amazon CloudFront を有効にする。EC2 や S3 を使っていても、CloudFront がそのまま使えるわけではない。明示的に有効にする(Sign Up)必要がある。</li>
<li>CloudFront で配信する object(ファイル)を S3 のバケットに用意する。</li>
<li>distribution を作成して domain name を得る。</li>
<li>domain name を用いてHTTPでアクセスする。</li>
</ol>
</p>

<h4>ツールのインストール</h4>
<p>perl のモジュールをインストールする。
<pre class="prettyprint">
# perl -MCPAN -e shell
Terminal does not support AddHistory.

cpan shell – CPAN exploration and modules installation (v1.7602)
ReadLine support available (try ‘install Bundle::CPAN’)
cpan> install Digest::HMAC_SHA1
cpan> install FindBin
cpan> install MIME::Base64
cpan> install Getopt::Long
cpan> install File::Temp
cpan> install File::Basename
cpan> install Fcntl
cpan> quit
Terminal does not support GetHistory.
Lockfile removed.
</pre>
</p>

<p>curl をインストールする。
<pre class="prettyprint">
# yum install curl
</pre>
</p>

<p>Amazon CloudFront Authentication Tool for Curl (cfcurl.pl) をインストールする。
<pre class="prettyprint">
# wget http://d1nqj4pxyrfw2.cloudfront.net/cfcurl.pl
</pre></p>

<p>Amazon用のcurlの設定ファイルを作成する。
<pre class="prettyprint">
# cat ~/.aws-secrets
%awsSecretAccessKeys = (
myaccount => {
id => ‘',
key => '',
},
);
# chmod 600 ~/.aws-secrets
</pre>
</p>

<h3>distribution を作成する</h3>
<h4>object (ファイル) を S3 bucket に用意する</h4>
<p>CloudFront での公開向けに新しい bucket を作成して、S3 Fox でディレクトリ毎ドラッグ&ドロップして楽をした。bucket のサブディレクトリのみ公開という設定ができないようなので、AMI などを保存している bucket と共用することはできないと思われる。</p>

<h4>distribution を作成して domain name を割り当ててもらう</h4>
<p>distribution とは、S3 bucket に格納した object(ファイル)を CloudFront に認識させるためのもの。S3 と CloudFront をつなげるのが distribution。ドメイン名を指定することはできない。
</p>

<p>distribution の作成リクエストを作成する。
<pre class="prettyprint">
# cat create_request.xml
<?xml version="1.0" encoding="UTF-8"?>
<DistributionConfig xmlns="http://cloudfront.amazonzws.com/doc/2008-06-30/">
yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>

true
</DistributionConfig>
</pre>
yourbucketname の部分には自分のバケットの名前を入れる。
</p>

<p>distribution の作成リクエストを送信する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -X POST -i -H "Content-Type:text/xml; charset=UTF-8" --upload-file create_request.xml https://cloudfront.amazonaws.com/2008-06-30/distribution

HTTP/1.1 100 Continue

HTTP/1.1 201 Created
ETag: E1A2X6NUDMD4NF
Location: https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Tue, 09 Dec 2008 06:07:52 GMT
Server: CloudFront

<?xml version="1.0"?>
<Distribution xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
[distribution ID]
InProgress
2008-12-09T06:07:52.160Z</LastModifiedTime>
yourdomainname.cloudfront.net

yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>

true
</DistributionConfig>
</Distribution>
☆実際は改行されていない。
</pre>
ドメイン名として yourdomainname.cloudfront.net が割り当てられた。yourdomainname の部分は、実際にはランダムに見える数字とアルファベットの羅列になる。
</p>

<p>デプロイ状態を確認する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]

<?xml version="1.0"?>
<Distribution xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
[distribution ID]
Deployed</Status&gt</span>
;2008-12-09T06:07:52.160Z</LastModifiedTime>
yourdomainname.cloudfront.net

yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
true
</DistributionConfig>
</Distribution>
☆実際は改行されていない。
</pre>
Deployed になった。
</p>

<h4>割り当てられたドメイン名を使ってHTTPでアクセスする</h4>
<p>http://yourdomainname.cloudfront.net/test.gif などでアクセスできることを確認する。ディレクトリを作成してある場合は http://yourdomainname.cloudfront.net/dir/test.gif となる。</p>

<h4>CNAME を使って独自ドメインでアクセスする</h4>

<p>yourdomainname.cloudfront.net のまま使っても良いのだが、きれいではない。そこで、独自ドメイン cdn.yourdomain.com に割り当てることにする。</p>

<p>まず、DNS で CNAME を設定する。ここでは、cdn.yourdomainname.com を yourdomainname.cloudfront.net に割り当てる。DNS で設定しただけで cdn.yourdomainname.com でアクセスすると "Sorry, invalid request" とエラーが返るので注意。</p>

<p>CloudFront に CNAME を設定する。まずは distribution configuration を取得する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -X GET -i https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]/config

HTTP/1.1 200 OK
ETag: E3UVV2001DSTPM
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Wed, 10 Dec 2008 01:45:59 GMT
Server: CloudFront

<?xml version="1.0"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
true
</DistributionConfig>
☆実際は改行されていない。
</pre>
</p>

<p>取得した XML に CNAME の設定を追加する。ここでは cdn.yourdomainname.com というドメインを設定した。
<pre class="prettyprint">
# cat add_cname_request.xml
<?xml version="1.0"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
cdn.yourdomainname.com</CNAME>
true
</DistributionConfig>
</pre>
</p>

<p>
リクエストを送信する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -X PUT -H 'If-Match: E3UVV2001DSTPM' -H 'Content-Type: text/xml; charset=UTF-8' --upload-file add_cname_request.xml -i https://cloudfront.amazonaws.com/2008-06-30/distribution/E34IPDB0XMHUZ8/config

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
ETag: E1R8F57QTNMIK7
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Wed, 10 Dec 2008 01:54:39 GMT
Server: CloudFront

<?xml version="1.0"?>
<Distribution xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
E34IPDB0XMHUZ8
InProgress
2008-12-10T01:54:39.556Z</LastModifiedTime>
daazlu5bwln5.cloudfront.net

yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
cdn.yourdomainname.com</CNAME>
true
</DistributionConfig>
</Distribution>
☆実際は改行されていない。
</pre>
</p>

<p>http://yourdomainname.cloudfront.net/test.gif などでアクセスできることを確認する。</p>

<h3>distrubution を削除する</h3>
<p>
ETag を取得する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -X GET -i https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]/config

HTTP/1.1 200 OK
ETag: E1A2X6NUDMD4NF
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Tue, 09 Dec 2008 06:49:07 GMT
Server: CloudFront

<?xml version="1.0"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
true
</DistributionConfig>
</pre>
</p>

<p>上記で得られた ETag と XML をどこかに保存しておく。XML の中の Enabled を false にして、PUT すると、distribution を disabled にできる。
<pre class="prettyprint">
-bash-3.2# ./cfcurl.pl --keyname gh -- -X PUT -H 'If-Match: E1A2X6NUDMD4NF' -H 'Content-Type: text/xml; charset=UTF-8' --upload-file disable_request.xml -i https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]/config

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
ETag: E1VR3TXI7JKY94
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Tue, 09 Dec 2008 07:43:19 GMT
Server: CloudFront

<?xml version="1.0"?>
<Distribution xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
[distribution ID]
InProgress
2008-12-09T07:43:20.254Z</LastModifiedTime>
yourdomainname.cloudfront.net

yourbucketname.s3.amazonaws.com
20081209150200</CallerReference>
false
</DistributionConfig>
</Distribution>
☆実際は改行されていない。
</pre>
</p>

<p>上記で得られた ETag の値を用いて distribution を削除する。
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -i -X DELETE -H 'If-Match: E1VR3TXI7JKY94' https://cloudfront.amazonaws.com/2008-06-30/distribution/[distribution ID]
</pre>
</p>

<h3>(おまけ)distribution の一覧を取得する</h3>
<pre class="prettyprint">
# ./cfcurl.pl --keyname gh -- -i -X GET https://cloudfront.amazonaws.com/2008-06-30/distribution

HTTP/1.1 200 OK
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Tue, 09 Dec 2008 08:02:09 GMT
Server: CloudFront

<?xml version="1.0"?>
<DistributionList xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">

100
false</IsTruncated>

[distribution ID]
Deployed
2008-12-09T06:45:12.827Z</LastModifiedTime>
yourdomainname.cloudfront.net
yourbucketname.s3.amazonaws.com
false
</DistributionSummary>
</DistributionList>
☆実際は改行されていない。
</pre>

<p>それにしても、S3 はコマンドラインから操作しようとすると、何をするのにも苦痛を伴う。普通は S3Fox などを使うほうがいい。
<ul>
<li>S3Fox は無料。v0.4.5 で CloudFront の distribution も操作できるようになった。
<li>Bucket Explorer は有料の Amazon S3、CloudFront の操作ソフト。CloudFront 対応はまだベータ版。しかも、ベータ版はお試し利用ができずに、ライセンスを購入する必要があるようだ。</li>
</li></ul>
</p>

ハイスピード英会話 その2 (High Speed English)

ハイスピード英会話(High Speed English)についてちょこっと書いたエントリにアクセスがあるようだ。もう2年前のことになるが、ホテルで行う5日間コースについて書いた文章があるので、ここに公開しようと思う。眠っているよりは、誰かの目にとまって何かの役にたつほうが、情報の価値があるというものだろう。

2008年時点でのハイスピードイングリッシュは、富士の自然の村研修センターと府中のホテルコンチネンタルの2箇所のみで行われている。自然の村研修センターは、主催する社員教育研究所自身が所有する施設である。環境が厳しいこともあって、訓練に適している。そう、訓練だ。学習や勉強ではなく、訓練。軍隊式と言ってもいいだろう。

私ははじめ、この自然の村研修センターの7日間コースに参加し、このストイックさが気に入り、その数ヵ月後に5日間コースの門を叩いた。この5日間コースはホテルアストン熱海で開かれた。現在は会場から外されてしまったホテルだ。私はこの2箇所での訓練しか知らない。ホテルコンチネンタルのことは知らない。それでも、参加を検討している方々の参考にはなると思う。

人の名前は全て伏字にした。オリジナル文章は仲間内で読んでもらうために書いたもので、全て固有名詞が入っていた。また、個人のプライベートに関わる話題も省いた。

2007年の初めころの話であるということを前提に、そして今はもう使われていないホテルだということに留意して読んで、参加への検討材料としてもらえれば嬉しい。

私自身は、もう行くことはないかもしれないが、あの2回の合宿は、今でもいい思い出として残っている。サバイバル的なトレーニングのおかげで、自分の英語力の壁をひとつ超えることができたと思う。7日間ないしは5日間の時間と、20万円弱のお金を投資した価値は、充分にあった。


teachers

今回の先生は、xxx と yyy でした。

HSE のシステムでは、毎回 head teacher を変えるそうです。正月休みのときは、xxx が head teacher で、今回は yyy が head teacher のはずなのですが、yyy の希望により、今回も xxx が head teacher でした。「今回は yyy なんだけどなぁ」みたいな感じで、xxx がぼやいて?いました。

students

生徒は10名。男性8、女性2です。placement test により A team と B team に5名ずつ、分かれました。color はありません。前回の方が人数が多いこともあり、レベル分けが2段階しかないのですが、A team にいた私としては、特に問題を感じることがありませんでした。Debate がないことも理由の一つかもしれません。

hotel

今回のホテルは、熱海のホテルです。熱海駅からタクシーで15-20分。遠いです。山の中です。何もありません。熱海の中でも、最も駅から遠いホテルの一つです。コンビニは車じゃないと行けません。ある生徒は、タクシーの運転手さんから「勉強には向いてますね」と言われたとか。

部屋は個室です。ツインの洋室を一人で使いました。部屋にはトイレがついています。風呂は大浴場のみ。大浴場は温泉らしいのですが、普通のお湯と区別がつきませんでした。先生に、あれって温泉なんですかと聞いたら "they say so."

食事は、富士よりは見た目が良いです。ただし、量に対して不満をもつ人が多かったように思います。xxx は夜中にホテルの自販機でカップ麺を買って食べてました。

レッスンする部屋には、ホテルの人が水とほうじ茶を用意してくれました。いつでも飲めます。紙コップなので、富士のようにカップを洗わずに済みます。

yyy に聞いてみました。いろんなホテルでやってるけど、どこでやるHSEが一番いい?と。そうしたら、「富士とここ(熱海)」以外ならどこでもいい、という答えが... 富士と熱海の共通項は "jail" だそうです。周りになにもないから、どこにも行けない。部屋でインターネットも使えない。

平日は、他のお客さんがほとんどいませんでした。大浴場(とても大きい)に行くと、私一人だけ。

プール付きであることがあらかじめ判っていたので、水着を持っていって3晩泳ぎました。夜プールに行くと、一人です。事故ったら危ないかもしれません。

party

今回は5日コースなので、party は4日目の夜のみです。富士のように風呂の時間を気にしなくていいので、2時間 + α(残った人のみ)楽しめました。ただし、食べるものが比較的短時間で無くなってしまいました。

motivation

生徒の motivation は、富士の方が高かったように感じています。私は、富士のコースでは日本語の会話を見かけなかったのですが、今回は、先生のいないところで時折日本語が話されていました。

集まった生徒の motivation が低いというよりは、環境によるものなのでは、と考えています。富士のコースは環境が貧弱で、サバイバル感がありました。今回はホテルで、文明の馨りがするし、ホテルの従業員との会話は日本語だし、他の宿泊客がいると英語を避けたい気分だしと、いろいろ悪条件が揃っていたことが原因ではないかというのが私の意見です。

(比較的)快適なところでレッスンを受ければ、心もゆるくなりますよね。他のホテルは、近所にコンビニがあったりするそうなので、もっとゆるい?

relationship between students

富士のコースのほうが、最終日の生徒間の関係は強いかもしれません。 一緒にいる時間という観点ですと、単純に 7日と 5日の違いのみではなく、

  • 宿題をするとき、自室でやるか教室でやるか

  • 寝室が個室か共用か

  • 風呂が一緒かバラバラか

  • 食事の準備をするか

という点にも差があります。

あとは、survival を感じさせる環境の影響ですかね。

戦争の戦友 >>> HSE富士の戦友 > HSEホテルコースの戦友

meal

富士よりは、見た目がはるかに良いです。味もまあ良いです。量は富士の方が 多いかも。先生たち(もっといいホテルをしっている人たち)にとっては 不満のようでした。生徒たち(もっと酷いところを知らない人たち)にとっても 不満のようでした。幸せだったのは私一人(富士しか知らない人)だけかも しれません。

今回、meal crew はありませんでした。chief もなく、食事の際の Are you ready? Let's begin もなく、4人がけのテーブル毎に、集まったテーブルから食べ始めていました。

食事に限らず、富士のコースに存在した様々な理不尽な?統制を取り除いたのが、ホテルでの HSE です。

lesson

7日間コースと 5日間コースのレッスン(訓練?)の違いを箇条書きでまとめます。

  • Debate が無い。

  • sports が無い代わりに、ホテル内での chatting またはホテルの外の散歩。

  • Problem Solving は Seafood Restaurant と Factory Tour。(同じ!)

  • Inverse Question Training は Zatouichi のみ。Nattou が無い。

  • Question Training は同じところまで進んだ気がする。3回/日やったりしたから。

  • lesson は 8:00-19:00

Lesson の教材は、もう何年も変わっていないそうです。zzzさんが過去に何度も変更を試みたけど、その度に上から拒否されてるそうです。残念。


関連エントリ

CentOS5 に Sun JDK + JPackage + tomcat をインストールする

<img src=”http://ec2.images-amazon.com/images/I/51m8phYZbyL.jpg” height=”120px”/ style=”float: left;”><img src=”http://ec2.images-amazon.com/images/I/51uK4ACymiL.jpg” height=”120px”/ style=”float: left;”><img src=”http://ec2.images-amazon.com/images/I/518TeUi%2BOwL.jpg” height=”120px”/ style=”float: left;”><img src=”http://ec2.images-amazon.com/images/I/517gQ0z6rGL.jpg” height=”120px”/ style=”float: left;”><img src=”http://ec2.images-amazon.com/images/I/51GRKN7J9XL.jpg” height=”120px”/ style=”float: left;”>




バージョン違いでインストールすると、ひどい目にあって時間を無駄に費やすことになる。

1. jpackage-utils をインストールする。 <pre class="prettyprint"># yum install jpackage-utils
</pre>2. Sun のサイトから jdk-6u6-linux-i586-rpm.bin をダウンロードする。 jpackage の RPM のバージョンに合わせるためにあえて最新でないものを取得。 3. jpackage の対応するパッケージを取得する。 <pre class="prettyprint"># wget
http://mirrors.dotsrc.org/jpackage/1.7/generic/RPMS.non-free/java-1.6.0-sun-compat-1.6.0.06-1jpp.i586.rpm
</pre>4. JDK をインストールする。 <pre class="prettyprint"># sh ./jdk-6u6-linux-i586-rpm.bin
</pre>5. JPackage の RPM をインストールする。 <pre class="prettyprint"># rpm -ivh java-1.6.0-sun-compat-1.6.0.06-1jpp.i586.rpm
</pre>6. Tomcat5.5 をインストールする。(これはついで) <pre class="prettyprint"># yum install tomcat5
</pre>

xenconsole: Could not read tty from store: No such file or directory

xen の console につなぐときに、このエラーメッセージが出るときは、
<pre class="prettyprint">xenconsole: Could not read tty from store: No such file or directory
</pre>

xenconsoled を立ち上げればよい。

でも、何故落ちたのだろう??? そっちの方が気になる。

<blockquote>xenconsole: Could not read tty from store: No such file or directoryでハマりました
http://d.hatena.ne.jp/kgbu/20080523/1211555660
</blockquote>

関連記事
<blockquote><ul><li>Xen の domainU のディスクを動的に増設する</li>
</ul>
</blockquote>