Cloudflare R2で圧縮コンテンツを保存および配信する方法と実用例

  • 2024-08-27
Cloudflare R2で圧縮コンテンツを保存および配信する方法と実用例

Cloudflare R2で実現!圧縮コンテンツを賢く保存・配信して、無料枠を最大限に活用する方法

皆さんは、Webサービスの運用コストの中で、ストレージや配信にかかる費用が意外と大きな割合を占めていることをご存知ですか? 特に、画像や動画、大量のデータファイルを扱うサービスでは、コスト削減のために頭を悩ませている方も多いのではないでしょうか。

私も先日、あるサイドプロジェクトで大量のGeoJSONファイルを扱うことになり、まさに同じ悩みを抱えていました。必要なファイル数はなんと約30万個! 圧縮前の容量は約11.5GBにもなり、無料枠の範囲内ではとても収まりそうにありません。

そこで目をつけたのが、Amazon S3の強力な代替サービスとして注目を集めている Cloudflare R2 です。R2最大の魅力は、なんといっても 10GBまで無料で使える 太っ腹なフリープラン。私の場合、gzip -9 で圧縮すれば1.5GB程度に収まるので、R2なら無料枠内で運用できる! と希望が見えた瞬間でした。

しかし、喜んでばかりもいられません。調べてみると、R2が圧縮ファイルをサポートしていることはフォーラムの投稿をいくつか見つけただけで、公式ドキュメントはほぼ皆無… 。これは困った… と思いながらも、開発者魂に火がつき、手探りで試行錯誤することにしました。

圧縮ファイルの準備:gzip を使って準備万端

まずは、ファイル名を維持したまま gzip でファイルを圧縮する作業から始めます。 以下のシェルスクリプトが便利です。

#!/bin/bash

for file in some-folder/*.geojson; do
    gzip -9 "$file"
    mv "$file.gz" "$file"
done

このスクリプトを実行すると、some-folder ディレクトリ内の拡張子 .geojson のファイルがすべてgzip圧縮され、元のファイル名で保存されます。拡張子が .gz に変わっていないことに注意してください。

rcloneの設定:R2をリモートストレージとして登録!

次に、R2をリモートストレージとして使うように rclone を設定します。 rclone は、様々なクラウドストレージサービスをコマンドラインから操作できる便利なツールです。

設定の前に、Cloudflareダッシュボードの R2 > 概要 > R2 APIトークンの管理 からAPIトークンを作成しておきましょう。

rclone 構成ファイルのパスは、以下のコマンドで確認できます。

$ rclone config file

表示されたパスにある構成ファイルを編集し、以下のような設定を追加します。

[some-bucket]
type = s3
provider = Cloudflare
access_key_id = <key>
secret_access_key = <secret>
endpoint = https://<bucket-id>.r2.cloudflarestorage.com
acl = private

<key><secret> は、先ほど作成したAPIトークンの値に置き換えてください。 endpoint は、R2バケットのURLです。

ファイルのアップロード:--header-upload オプションが成功のカギ!

準備が整ったら、いよいよ rclone を使ってR2にファイルをアップロード!…といきたいところですが、ここで重要な注意点があります。

単に rclone copy コマンドを実行しただけでは、R2はファイルが圧縮されていることを認識してくれず、アップロードは失敗に終わります。

そこで登場するのが、 --header-upload オプションです。このオプションを使うことで、アップロードするファイルに関する追加情報をR2に伝えることができます。

$ rclone copy --progress --header-upload "Content-Type: application/json" --header-upload "Content-Encoding: gzip" some-folder some-bucket:bucket-path/

--header-upload "Content-Type: application/json" は、アップロードするファイルのContent-Typeが application/json であることをR2に伝えています。 --header-upload "Content-Encoding: gzip" は、ファイルが gzip で圧縮されていることを伝えています。

これらの情報があることで、R2は圧縮ファイルを正しく認識し、解凍せずにそのまま保存してくれます。ちなみに、 --header だと動作しないので注意が必要です。

圧縮コンテンツの効果:ストレージ容量の節約だけじゃない!

これで、圧縮された状態のままR2バケットにファイルが保存され、アクセスできるようになりました。gzip 圧縮によって、ストレージ容量を大幅に節約できただけでなく、配信時に必要な帯域幅も削減できるため、コスト削減効果は抜群です!

さらに、R2はクライアントからの Accept-Encoding ヘッダーにも対応しているので、gzipbrotli、プレーンテキストなど、クライアントの環境に応じて最適な形式で転送してくれます。

ちなみに、brotli圧縮も使えますが、クライアントの Accept-Encoding ヘッダーに関わらず、brotliとしてのみ配信されるようです。

まとめ:R2で実現する、スマート&エコノミカルなWebサービス運用

今回の学びを活かして、私は iNaturalist の観察データを地図上にヒートマップ表示するサービス (https://inat-map.birdi.ng) を開発しました。R2の圧縮ファイルサポートのおかげで、大量のGeoJSONファイルを効率的に保存・配信できています。

皆さんも、R2の圧縮機能を有効活用して、スマート&エコノミカルなWebサービス運用を目指してみてはいかがでしょうか?

元記事: Using R2 to store and serve compressed content