Net::Azure::StrageClientモジュールを書いてCPANデビューした話。
公開日 : 2013-12-19 00:00:01
この記事はPerl Advent Calendarの19番目のエントリーです。
Net::Azure::StorageClient モジュールを作ってCPANデビューしました。
11月に Net::Azure::StorageClient というモジュールを作って、CPANデビューしました。Azureの Advent Calendar でこのモジュールの紹介をしようと思っていたのですが、Mac用クライアントを作ったのでそっちの話題にしてしまったので、こっち(どっちだ)に書こうかと。
モジュールの利用方法
use Net::Azure::StorageClient::Blob;
my $blobService = Net::Azure::StorageClient::Blob->new(
account_name => $you_account_name,
primary_access_key => $your_primary_access_key,
container_name => $container_name, );
my $path = 'path/to/blob';
my $res = $blobService->get_blob( $path );
戻り値は HTTP::Response object(s)です。 詳細はドキュメントを見ていただくとして、Azure Blob APIにある一通りの機能は実装してあります。それ以外にいくつか便利なものが。例えばダウンドードはこんな感じで
my $res = $blobService->download( $container . '/' . $path, $local_path, $params );
アップロードは以下のようになります。
my $res = $blobService->upload( $container . '/' . $path, $local_path, $params );
download/upload は実はフォルダ指定にも対応しています。downloadは、コンテナ指定もできます。
マルチスレッドによる高速ダウンロード/アップロード
Threadが利用可能な時、ディレクトリを指定するときに、$params に { use_thread => 10 } を与えるとマルチスレッド(スレッド数の上限が10)で高速に処理を実行できます。
Windows Azure Blob APIのいくつかのTips
せっかくなので、ハマったこととか、ドキュメントがなくて悩んだことなどを。何せ、書籍も古いものしかないので(買ったけど)。
ディレクトリの扱い
ディレクトリ以下のBlob一覧を得るには、リクエストに prefix=パスの開始文字 を追加します(厳密にはディレクトリという概念はないのですが、例えばパスに / のような文字列を指定して擬似的にディレクトリのように扱うことができます)。
my $res = $blobService->list_blobs( $container_name, { options => 'prefix=directory_name/' } );
この時、ディレクトリ直下のアイテムのみを得るには(そうでないと、大量のコンテンツを含む上位ディレクトリほど処理が重くなる)、delimiterオプションを付与します(大量のコンテンツのある上位ディレクトリの表示にCloudXplorerとかめっちゃ速くてどうやってんだろ、これみたいなことで英文の技術ブログなんか読みあさって試行錯誤して発見したのでした...)。
my $res = $blobService->list_blobs( $container_name, { options => 'delimiter=/&prefix=directory_name/' } );
5000件を超えるBlobのリスト取得
my $res = $blobService->list_blobs( $container_name );
とすると、コンテナ以下のBlobの一覧を取得しますが、5000件の制限があります。5000件を超える場合、取得したXMLに NextMarker という要素があるので、この値を marker パラメタに渡してやります。
my $res = $blobService->list_blobs( $container_name, { options => 'marker=' . $marker } );
この時、$NextMarker をURLエンコードしてやらないといけません。というか、エンコードしないとあかん文字列がAPIから返ってくるのでした。
my @responses;
my $res = $blobService->list_blobs( $container_name );
push ( @responses, $res );
my $xml = XML::Simple->new;
my $data = $res->content;
my $list = $xml->XMLin( $data );
$marker = $list->{ NextMarker };
$marker = undef if ( ( ref $marker ) eq 'HASH' );
while ( $marker ) {
$marker =~ s!([^a-zA-Z0-9_.~-])!uc sprintf "%%%02x", ord($1)!eg;
$res = $blobService->list_blobs( $container_name, { options => 'marker=' . $marker } );
...
Net::Azure::StrageClient::Blobのlist_blobsでは、この辺りの処理は自動的にやってくれます。 冒頭に「HTTP::Response object(s)です。」と書きましたが、(s)というのは、list_blobs等の場合は自動的に再帰的にリクエストを送って HTTP::Response object の配列を返すようにしているからです。
といった感じで、これ、PerlからAzureのBlobを扱うのに便利なモジュールですよ。