2010年9月11日 (土)

CloudFrontのエッジサーバ上にキャッシュされているオブジェクトを更新する

こんにちは。フレクトの大橋です。

私たちが運営しているベターホームレシピ(http://bhmb.jp)では、画像などの静的コンテンツ
の配信にCloudFrontを使っています。

CloudFrontはAmazonが用意しているS3上のオブジェクトを高速に配信する仕組みです。
CloudFrontを使うと、S3のオブジェクトがエンドユーザに対して近くに配置されている
サーバ(エッジサーバ)から配信されるようになり、高速のコンテンツの配信ができます。アメリカ西海岸にあるS3の画像が日本国内のエッジサーバにキャッシュされて、高速に配信できたりします。CDN(Contents Delivery Network)の一種です。

CloudFrontのエッジサーバはオブジェクトへのアクセスがあったときに、もしエッジサーバ上に
オブジェクトがあれば、それを配信し、なければ、S3にアクセスしにいき、
配信します。S3から取得したオブジェクトはエッジサーバ上にキャッシュされます。

キャッシュされる時間はS3のメタデータ(HTTPヘッダなど)にTTLを設定すれば制御できます。
以前は24時間が最短でしたが、現在は1時間を最短にできます。
Expireヘッダに1時間後の時間を設定するなどすれば、1時間ごとにエッジサーバのオブジェクトは
更新されるようになるはずです。詳しくは以下を参考にしてください。

http://aws.typepad.com/aws/2010/04/amazon-cloudfront-object-ttl-slashed.html

■ キャッシュが1時間単位だとけっこう面倒

さて、前置きが長くなりましたが、ベターホームレシピではデザイナが
直接S3にアップして静的コンテンツを確認したりします。(もちろん、開発用環境からやりますが)
しかし、以下のような問題によくぶつかっていました。

 ・静的コンテンツ(画像、CSS)などを更新しても、HTML内はCloudFrontのURLを
  指しているので、1時間以上待たないと更新が確認できない。
 ・デザイナがExpireヘッダなどいちいち意識するのはとても面倒

うちのデザイナは技術力もあるため、S3を直接触るような運用になっている事情もあるのですが、
何かとこのキャッシュのタイミングは面倒な作業が発生していました。

そのため、

「CloudFront上のコンテンツをゴリゴリ編集できるようにしたい、もうキャッシュ切れを待つのは面倒」

という不満がチーム内(デザイナだけですが)にただよっていました。

■ CloudFrontのInvalidation機能

そうしたら、最近以下のような記事を見つけました。
英語の苦手な私は早速スルーしようと思いましたが、ちょっとだけ読んでみると、
どうやら、CloudFront上のエッジサーバのキャッシュを無効にできる機能が
CloudFront API上に実装されたようです。

http://aws.typepad.com/aws/2010/08/new-cloudfront-feature-invalidation.html

用途としては

 ・まれに実施するCSSやJavaScriptの更新
    → ただし、1時間とか1日待つのは面倒ですよね
 ・間違ってエンコードしたビデオファイルをキャッシュから削除

などなどがあがっています。

■ CloudBuddy PersonalでInvalidation機能の使う

「APIが用意されているので、そちらでどうぞ。」

http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=213

と言いたいところですが、現実的にはうちのデザイナはそこまでは
やってくれませんし、そんなことを要求したら喧嘩になりそうなのでやめておきます。
以下の2つのツールが現状は対応しているようです。

   ・CloudBuddy Personal
   ・CloudBerry Explorer

前者で実施してみました。

まずは CloudBuddy Personalをインストールします。

  http://m1.mycloudbuddy.com/downloads.html

メールアドレスなど入力が必要ですが、画面に出てくる指示のままに
進めます。

ダウンロード、インストール後、S3のアクセスキー、秘密キーなどを
入力して、CloudBuddy Personalのエクスプローラ画面を開いてください。

CloudFrontに対応したバケットを選択し、右クリックを押して
以下のように「Object Invalidate」を押してください。

Cf_inv_01

次の画面で、「Distribution」のURLとInvalidateしたいオブジェクトを選択し、
「Create New Invalidation」を押します。

Cf_inv_02

そうすると、たぶん、5分から10分くらいでキャッシュが無効になっているはずです。
リアルタイムじゃないのでご注意ください。
Invalidationする前に、該当のオブジェクトを更新するなりしておくと
ちゃんと確認できます。

CloudBuddy Personalのエクスプローラの右上のCloudFrontボタンから
たどれるCloudFront Consoleでも、Invalidation Listで無効にしたキャッシュオブジェクトの
リストが以下のように確認できます。

Cf_inv_03

はい、このエントリは若干長いですが、CloudFront上のキャッシュオブジェクトの更新は
けっこう簡単です。そして、実際に使うときも技術的なことはほとんど考えなくてよいです。

まだ開発者の私しか試していないので、来週、うちのデザイナに試してもらおうと
思います。きっとこれまでの不満を解消できることでしょう。

フレクトではCloudFrontやS3を使ってデザイナと一緒にコンテンツ運用の
「よりよい仕組み」を作っていけるエンジニアを募集しています。
興味のある方は以下からどうぞ。

 

http://www.flect.co.jp/recruit/index.html

 

2010年8月19日 (木)

PerlでAmazon S3の操作をする方法

今日はPerlとS3についてです。

EC2上で稼働しているベターホームレシピ(http://bhmb.jp/)では
サーバ側の細かい運用ツールにPerlを使っているケースが多いです。

また、静的コンテンツの公開やログデータのバックアップなどには
Amazon S3を使っています。

s3syncなどS3を使うツールはありますが、プログラム経由で操作したい
ケースもそれなりにあり、Perlのモジュールを使ってAPI経由で
S3を操作し、各種運用をしています。その方法について簡単に紹介します。


[モジュールの選定]

PerlでS3を使うには

 ・Net::Amazon::S3
 ・Amazon::S3

あたりのモジュールが代表的なようです。この2つで検討しました。
Net::Amazon::S3の方がドキュメント、機能、パフォーマンスはよさそうすが、

  「依存モジュールが少ないこと。インストールしやすいこと。」

を重視したいので、Amazon::S3の方が私たちのケースではよさそうでした。

Net::Amazon::S3はAmazon::S3の3倍くらい依存モジュールがあり、XML::LibXMLやMooseなど
ブツブツいうほどでもないですが、ちょっとインストールが面倒なケースがあったり、重量級モジュール
だったり、と「お手軽感」という点では少しマイナスかな、と思いました。

ドキュメントみたら、やっぱりNet::Amazon::S3よりポータブルにするという思想があるみたいですね。

http://search.cpan.org/~tima/Amazon-S3-0.45/lib/Amazon/S3.pm

XML::LibXMLを使わないなどパフォーマンス面は少し劣るようですが、「ポータブルな実装」っていうのは
Goodです。パフォーマンスはとりあえず、気にしないことにしました。

ただ、Amazon::S3はちょいとドキュメントがゆるいというのが欠点はあります・・・。
まあ、中身を読んだりすれば何とかなるだろう、ということで、
よしあしはありますが、私のケースではAmazon::S3に決定して、
ベターホームレシピではPerlでS3の操作をしています。

では、簡単ですが、使い方サンプルを。


[インストール]

最近はもっぱらcpanminusでモジュールインストールです。

 cpanm Amazon::S3

とかでOKです。

以下あたりを参考にすると、cpanminusの簡単な使い方が書いてあります。

http://www.omakase.org/perl/cpanm.html


[S3への接続]

まず、接続編。以下のようにAmazon::S3クラスのコンストラクタを
アクセスキー、秘密キーを指定して呼び出せば、S3を操作するオブジェクトを
取得できます。

#!/usr/bin/perl

use strict;
use warnings;

use Amazon::S3;

# S3のアクセスキーの指定                                                                                 
my $aws_access_key_id     = 'それぞれの環境ごとに指定してください。';
# S3の秘密キーの指定                                                                                     
my $aws_secret_access_key = 'それぞれの環境ごとに指定してください。';

my $s3 = Amazon::S3->new(
    {
        aws_access_key_id     => $aws_access_key_id,
        aws_secret_access_key => $aws_secret_access_key
    }
);

my $res = $s3->buckets;

# 成功していればownwer_idなどが取得できます
print $res->{owner_id} . "\n";
print $res->{owner_displayname} . "\n";

[S3のバケット一覧の取得]

ドキュメントに記載されていないように見えましたが、
取得したS3オブジェクトを使ってバケット名一覧を取得できるみたいです。

my @buckets = @{$s3->buckets->{buckets}};

for my $bucket ( @buckets ) {
    print $bucket->bucket . "\n";

}


[S3のバケット作成]

これはドキュメントにサンプルがあるとおりですが、バケット作成は
こんな感じみたいです。バケット名を指定すればOKですね。

my $new_buekct = $s3->add_bucket( { bucket => 'flect_test_buekct' } )
    or die $s3->err . ": " . $s3->errstr;


[S3へのデータのアップロード]

データをアップロードするだけならば、サンプルにもあるとおり
以下のような感じです。

# バケットオブジェクト( Amazon::S3::Bucketのオブジェクト )を取得                                          
my $bucket = $s3->bucket('flect_test_buekct');

# キーを指定                                                                                             
my $keyname = 'test.txt';

# 値を指定                                                                                                
my $value   = 'T';
$bucket->add_key(
                  $keyname,
                  $value,
                  {
                      content_type        => 'text/plain' # コンテンツタイプなど設定を指定                                                                        
                  }
                  );

ローカルディスクにあるファイルを指定してアップする場合は以下のように
add_key_filenameを使います。

my $filepath = './testfile.txt';
$bucket->add_key_filename( 'testfile.txt', $filepath )
  or die $s3->err . ':' . $s3->errstr;

ファイル指定してアップロードというユースケースもけっこうあるので
よく使います。


[S3の指定したバケット内のキーリストを取得]

ファイルをアップしたりすれば、当然取得したくなります。
これもサンプルどおりですが、一応書いておきます。

# バケットオブジェクト( Amazon::S3::Bucketのオブジェクト )を取得                 
my $bucket = $s3->bucket('flect_test_buekct');

# キーリストを取得。                  
my $res = $bucket->list
    or die $s3->err . ": " . $s3->errstr;

# キーリストを表示                  
for my $key (@{ $res->{keys} }) {
    print $key->{key} . "\n";
}


[S3のバケット内に指定したキーが存在するかの確認]

既に同一キーでオブジェクトがアップされていないか、など確認したくなる
ケースがあります。そんな場合は以下のような感じで。

# バケットオブジェクト( Amazon::S3::Bucketのオブジェクト )を取得                  
my $bucket = $s3->bucket('flect_test_buekct');

# head_keyでキーの存在確認ができます。                  
if ( $bucket->head_key("testfile.txt") ) {
    print "key is found\n";
} else {
    print "key is not found\n";
}


[S3からデータのダウンロード]

S3に退避しておいて、別の場所でダウンロードしたい、なんてことありますよね。
ベターホームレシピではログファイルをEC2からS3にアップし、社内のデータ解析用サーバに
ダウンロードしていろいろ処理しています。

データをダウンロードし、その値をPerl内でごにょごにょ処理したい場合は
以下のように。

# バケットオブジェクト( Amazon::S3::Bucketのオブジェクト )を取得
my $bucket = $s3->bucket('flect_test_buekct');

# キーを指定してPerlの変数に取得。                  
my $data = $bucket->get_key('testfile.txt');
# 値を表示。valueを指定。                  
print $data->{value} . "\n";

データをローカルのファイルシステムに保存したい場合は以下のように。

# バケットオブジェクト( Amazon::S3::Bucketのオブジェクト )を取得
my $bucket = $s3->bucket('flect_test_buekct');

# 最後の引数にダウンロードするパスを書く。
$bucket->get_key_filename( 'testfile.txt', 'GET', './donload_file.txt' )
    or die $s3->err . ':' . $s3->errstr;


[S3からキーを削除]

アップしてあるデータを削除するには

my $bucket = $s3->bucket('flect_test_buekct');
$bucket->delete_key('testfile.txt')

みたいにしましょう。簡単です。


[最後に]

アクセス権制御や、各種メタデータの格納などは今回はカバーしていませんが、
次回以降、どこかでまたまとめて書きたいと思います。

Google Storageなど対抗のサービスもありますが、S3はいろいろな用途で
大活躍できるので、もっと調査、活用を考えてみたいです。

なお、フレクトではAmazon EC2/S3を利用した開発、案件をこれから
たくさんやっていきます。興味のある方はぜひ中途採用にご連絡ください。

http://www.flect.co.jp/recruit/index.html

2010年8月 4日 (水)

Amazon EC2/S3, Google AppEngine, Google Appsで開発、運用するモバイルレシピサイト

フレクトの大橋です。このブログではフレクトで運営しているサービスについての
開発情報をなるべくオープンに公開しきたいと思います。

1回目はAmazon EC2/S3, Google Appsなどを使って開発したモバイル3キャリア公式サイト
のシステム構成について紹介します

サイトはお料理教室のレシピが携帯でチェックできる「ベターホームレシピ」です。

システムとしては携帯からレシピコンテンツを各種検索機能やランキング機能を
使って探すことができるサイトとお考えください。

今後、システム開発に使った技術は当ブログで詳細を紹介していきますが、
今日のところはどんな要素でシステムを組んだのか、参考になる方も
いらっしゃるかも、ということで公開してみます。

まず、システム構成の概略図を。

Bh_arch

【インフラ】

・Amazon EC2(アメリカ西海岸)
   開発中にシンガポール版が出たのですが、リリースが近かったので
   検証できず、アメリカ西海岸でスタートとなりました。

【OS】

・Linux(CentOS)

【Web/APサーバ】
 ・Apache
 ・Tomcat

【アプリケーション実装】

 ・主にJava、一部Perl/Pythonです。
 ・WebアプリのフレームワークにはSAStruts/S2JDBCを使いました。
 ・また、携帯用処理にはmobyletを使いました。mobylet便利です。

【データベース】

 ・MySQL
   特段かわったことはしていませんが、
   データファイルはAmazon EBSにおいて運用し、
   そのスナップショットを定期的にS3にアップするよう
   運用しています。

【検索サーバ】

 ・Apache Solr
  ⇒ 何かと高性能な検索エンジンです。今度ブログ記事を
    記載したいと思いますが、形態素解析でやっています。
    網羅性より精度重視で構築しました。

【レコメンドサーバ】

 ・Cicindela
  ⇒ ライブドアさんが作ったOSSのレコメンドエンジンです。
    Perlでできていて、一部フレクトでフィルタ等追加して
    構築しました。

【メール送信】

 ・Postfix
  ⇒ いたってノーマルな使い方をしています。

【空メールの受信】

 ・GoogleAppEngine
  ⇒ smtp2webじゃないですが、同じようなことをするために
    メール受信のハンドリングはGoogleAppEngineで行いました。
    Pythonでアプリ部分は実装しています。

【画像配信】

  ・Amazon CloudFront

【運用監視】
  ・muninや自作ツールなど

【バックアップ用ストレージ】

・各種バックアップはAmazon S3を使っています。データベースのバックアップや
 ログのバックアップに使っています。

【効果測定、ログ集計・視覚化】

  ・Google Analytics
  ・自作ツール+ Google Spreadsheets

EC2/S3, GAEを使っているところがポイントですが、もう事例も多いので
目新しくないかもですね。

ちょっと珍しいかも、というのはログ集計・視覚化にGoogle Spereadsheets API
を使って集計値を更新したり、グラフを更新したりして、チームみんなで
アクセス状況、コンテンツの人気度の分析など行っていることでしょうか。

今後、詳細をいろいろ公開していきます。

最後にPR。

フレクトでは、Amazon EC2/S3を使ってシステムを作ってみたい!Google Appsを
使ってちょっと便利なツールを作ってみたい!という意欲あふれるエンジニアを
募集しています。興味のある方はぜひ以下からご連絡ください。

中途採用応募はこちら

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上での
Webアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、セールスフォースパートナーです。
また、heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。

2024年5月

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
ブログ powered by TypePad