Amazon S3を33%安く使う方法
暑いですね、汗 汗 汗(汗3)。
Amazon Simple Storage Service、略してS3というストレージサービスがあります。
少し前に、Amazon Web Services BlogでReduced Redundancy Storage(Amazon RRS)が発表されました。
http://aws.typepad.com/aws/2010/05/new-amazon-s3-reduced-redundancy-storage-rrs.html
簡単に説明すると、S3の可用性は99.999999999%ですが、RRSは99.99%となっていて少し可用性が低いので33%安く利用出来ますよという事です。
blogから引用
RRS pricing starts at a base tier of $0.10 per Gigabyte per month, 33% cheaper than the more durable storage.
99.999999999%と99.99%の差で33%安いとなれば、お薦めですね。
使い方
http://docs.amazonwebservices.com/AmazonS3/latest/index.html?DataDurability.html
肝心な使い方ですが、コマンドベースだとs3cmdにx-amz-storage-class:REDUCED_REDUNDANCYつけてあげるだけですので、簡単ですね。
しかし、これだと新規でputする場合にしか使えません。
既存のS3に保存してあるファイルをRRSに置き換えたいという人が多いと思います。
その場合は、x-amz-storage-class: REDUCED_REDUNDANCYとx-amz-metadata-directive: COPYを付けてあげればよいです。
PUT /my-image.jpg HTTP/1.1 Host: bucket.s3.amazonaws.com Date: Wed, 28 Oct 2009 22:32:00 GMT x-amz-copy-source: /bucket/my-image.jpg Authorization: AWS 0223123223RW0EXG2:0RQf4/cRonhpaBX5sCYVf1bNRuU= x-amz-storage-class: REDUCED_REDUNDANCY x-amz-metadata-directive: COPY
これで安くS3が使えて嬉しいなと言いたいところですが、S3のコンソールにはstrage-class情報は表示されていません(2010/07/14の時点)。
表示可能なものは無いか探したところ、ありました、S3 Browser!
S3 Browser
http://s3browser.com/working-with-reduced-redundancy-storage-rrs.php
早速ダウンロードして使ってみると、Strage Classのプロパティが表示されるうえに
strage-classをREDUCED_REDUNDANCYに変更してApplyするだけで変更されます。
しかも、あるじゃないですか、まとめて一括変換!これがやりたい!!
□Apply to Child object
チェックを入れてApplyすれば一気に変換してくれると思いチェックボックスをチェックすると
世の中甘くないですね><
AWS SDK for Java
普段、よくEclipseを利用しているのでAWS SDK for Javaで、まとめてやればいいんじゃないかと思い、やってみました。
指定バケット配下のファイルを全てRRSに変更します。
package yone098; import java.io.IOException; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.Headers; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ListObjectsRequest; import com.amazonaws.services.s3.model.ObjectListing; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectSummary; import com.amazonaws.services.s3.model.StorageClass; public class S3Rrs { public static void main(String[] args) throws IOException { String accessKeyId = "アクセスキー"; String secretAccessKey = "シークレットアクセスキー"; AWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); ClientConfiguration configuration = new ClientConfiguration(); configuration.setSocketTimeout(60 * 1000 * 3); AmazonS3 s3 = new AmazonS3Client(credentials); String bucketName = "指定するバケット名"; long start = System.currentTimeMillis(); try { // 一覧取得 ObjectListing objectListing = s3 .listObjects(new ListObjectsRequest() .withBucketName(bucketName)); final String REDUCED_REDUNDANCY = StorageClass.ReducedRedundancy .toString(); // copy指定metadata final ObjectMetadata metaData = new ObjectMetadata(); metaData.setHeader(Headers.METADATA_DIRECTIVE, "COPY"); for (S3ObjectSummary objectSummary : objectListing .getObjectSummaries()) { System.out.println("file name = " + objectSummary.getKey() + " " + "(size = " + objectSummary.getSize() + ")" + " (strage class = " + objectSummary.getStorageClass() + ")"); final String keyStr = objectSummary.getKey(); final String storageClass = objectSummary.getStorageClass(); final String bucket = objectSummary.getBucketName(); // StrageClassがRRSじゃない場合にのみRRSに if (!REDUCED_REDUNDANCY.equals(storageClass)) { long start1 = System.currentTimeMillis(); S3Object object = s3.getObject(new GetObjectRequest( bucketName, keyStr)); PutObjectRequest req = new PutObjectRequest(bucket, keyStr, object.getObjectContent(), object.getObjectMetadata()); // RRSの指定を行う req.setStorageClass(StorageClass.ReducedRedundancy); req.setMetadata(metaData); s3.putObject(req); long end1 = System.currentTimeMillis(); System.out.println(" time=" + (end1 - start1) + "ms"); } } System.out.println(); long end = System.currentTimeMillis(); System.out.println("### All time = [" + (end - start) + "]ms ###"); } catch (AmazonServiceException ase) { System.out .println("Caught an AmazonServiceException, which means your request made it " + "to Amazon S3, but was rejected with an error response for some reason."); System.out.println("Error Message: " + ase.getMessage()); System.out.println("HTTP Status Code: " + ase.getStatusCode()); System.out.println("AWS Error Code: " + ase.getErrorCode()); System.out.println("Error Type: " + ase.getErrorType()); System.out.println("Request ID: " + ase.getRequestId()); } catch (AmazonClientException ace) { System.out .println("Caught an AmazonClientException, which means the client encountered " + "a serious internal problem while trying to communicate with S3, " + "such as not being able to access the network."); System.out.println("Error Message: " + ace.getMessage()); } } }
10Mのファイルを60ファイルほど一括でRRSにしてみたところ、10Mのファイル1つの変更で約200〜300秒かかりました。
会社帰りに流しておくと良いのではないでしょうか。
監視社会
S3のコンソールからはRRSかどうか確認出来ないし、RRSにも変更出来ないから
S3にあるファイル群を一括RRSにするプログラム書いたんだよねーなんて話していたら、数時間後にAWS Blogに以下のpostが。
AWS Management Console Support for S3 RRS
http://aws.typepad.com/aws/2010/07/aws-management-console-support-for-s3-rrs.html
早速使ってみると、コンソールからRRSかどうか確認出来る上にRRSに更新まで可能になってます。
さすがですね、Amazonさま!
まるでAmazonに私がCloud Watchされてるかのようなタイミングでした。
S3BrowserのようにRRSかどうかを参照しつつ、更新出来るものは需要あるだろうから作って公開しようかななんていた矢先の事です。
しかしS3のコンソールでは、S3 Browser Proにあるようにバケット指定で一括変換はまだ対応されてないようです。
ということで、現在無償で一括でRRSにするものは無いと思いますので、是非、使ってみてください(自己責任でお願いします)