この記事では、ウェブサイトの画像サイズを変更すべき理由と、GCPロードバランサーとCloud CDNを備えたGoogle Cloud Functionsを活用してオンザフライでリサイズ画像を配信し、ウェブサイトのパフォーマンスを向上させ、高価なストレージスペースを節約し、ウェブサイトの読み込み時間を改善する方法について説明します。
ほぼすべての主要なウェブサイトは、サイトに表示される写真のサイズを変更しているが、その理由は主に3つある:
- 大きな画像をダウンロードすると、帯域幅の使用量が多くなり、データ転送コストが高くなります。
- HTML経由で画像を縮小する場合、クライアント・ブラウザは画像全体をダウンロードし、そのサイズ変更にCPU時間を費やす必要があるため、ウェブサイトの読み込み時間が遅くなります。
- オンザフライでリサイズしない場合、同じ画像をデスクトップ、モバイル、タブレット、Eメール(ニュースレター)用に異なるサイズで保存する必要があります。
画像の最適化については、スティーブ・サウダーズの著書をお読みください、 さらに速いウェブサイト第10章.
Google Cloud Content Delivery Network (CDN)を使用することで、オブジェクトが世界中に広がるエッジネットワークにキャッシュされるため、静的コンテンツのロード時間を短縮することができます。

この記事のソリューションは、以下のサービスを使用している:
- Google Cloud Storage - 画像をフルサイズで保存します。
- クラウド機能 - オブジェクトのサイズをその場で変更できます。
- Cloud CDNが有効なGoogle Cloud Load Balancer - ユーザーは画像を取得するためにロードバランサーにアクセスします。
GCPクラウドロードバランサー(LB)を作成し、クラウド関数を呼び出すように設定します。関数はGoogleクラウドストレージ(GCS)から画像を取得し、サイズを変更します。

配備方法
Googleクラウドストレージ(GCS)バケットを作成し、すべてのオブジェクト(画像)をオリジナルサイズでアップロードする。

バケツの名前を設定し、地域ロケーションを設定し、作成ボタンをクリックする:

例えば、nasdaq.jpg(タイムズ・スクエアのナスダック・ビル、2019年に撮影)という画像を、オリジナル・サイズの6.3MBのままこのバケツにアップロードした。

次のステップは関数を作成することです。Cloud Functionsコンソールに行き、Write a functionをクリックします。

Cloud Functionsを初めて使用する場合、"Cloud Functions API is enabled "というメッセージが表示されるかもしれません。これは、追加料金なしでプロジェクトでCloud Functionsの機能が有効になっていることを意味します。
このステップでは、関数を設定する必要がある:
- 私たちはインライン・エディターを使っています。
- 関数の名前を設定する。
- 地域を選択する -GCSの地域と同じでなければならない。
- ランタイムを設定する。このデモではPythonを使っている。
- そしてIAM認証のチェックを外し、LBが関数を呼び出せるようにする。

初めてGCPサービスを使用する場合は、さらにいくつかのAPIを有効にする必要があるかもしれません:

実際にGCSからファイルを取り出し、リサイズして、リサイズされたファイルを返すコードを書く必要がある。
ChatGPTだけでできるかどうか試してみたかったので、以下のようなプロンプトを書いた後、LLMと何度か繰り返した:
"提供された文字列に基づいてjpg png画像をx,yにリサイズするPythonコードを書く"
"googleクラウドの関数で、パラメータをクエリー文字列として渡し、ファイルをgcsからロードする必要があり、その結果を適切なmimeタイプでロードバランサーに送る必要があるとします。"
"このコードのrequirements.txtには何を書けばいいですか?"
"現在、「Error processing image: module 'PIL.Image' has no attribute 'ANTIALIAS'」が表示されています。
その結果が以下のコードである。9行目で、使用するバケツを設定する:

これはCloud Functionsを設定するためのrequirements.txtファイルで、コンテナを構築するためにどのPythonライブラリを使うかを設定する:

main.pyのコードとrequirements.txt のライブラリを更新すると、"The specified function (entry point) may not be present in your source code.あなたのコードのエントリポイントが入力フィールドと一致していることを確認してください。" という警告が表示されます。
これは、この関数がresize_image 関数を呼び出しているためで、Cloud Functionsのデフォルトの関数名は hello_httpです:

Functionのエントリーポイントを resize_imageに 変更し、Save and redeployをクリックします。
Cloud Functionsがコードのコンテナをビルドします。数分かかるかもしれませんが、ダッシュボードの上部でビルドのステータスを追跡できます:

注:Cloud Functionは関数を呼び出します。この関数はCompute Engine Default Service Accountを使用し、プロジェクト内の全てのGCS Bucketsへのアクセスを関数に付与します。この記事では取り上げませんが、ベストプラクティスとして、最小権限のアクセス権を持つ専用のサービスアカウントを使うべきです。
次のステップはロードバランサーの作成です。サーチコンソールで "Load Balancer" を検索し、ロードバランサーダッシュボードにアクセスし、ロードバランサーの作成をクリックします:

ロードバランサのタイプで、Application Load Balancer (HTTP/HTTPS)を選びます:

世界中のユーザーがロードバランサーにアクセスできるようにしたいので、パブリックフェイシング(外部)を選びます:

Google Cloud CDNの機能を活用するためにGlobalロードバランサーを選びました。これにより、リサイズした画像をエッジサーバーにキャッシュすることができます(追加費用なし)。

そして、最新のロードバランサージェネレーションを選択し、 Nextと Create ボタンをクリックします。

この段階を簡単にするために、ロードバランサーのHTTPフロントエンドエンドポイントを作ります。
ロードバランサーの名前とフロントエンドのIPを設定します。

Backend Configurationをクリックし、Backend services & backend bucketsボックスで、Create backend service をクリックします。

バックエンド・サービスの名前と説明を設定し、Backend typeを Serverless network endpoint groupに変更する。

Backendsエリアまでスクロールダウンする。New backend」の下にある「Serverless network endpoint groups」をクリックし、「Create Serverless network endpoint group」をクリックする。

エンドポイントの名前を設定し、クラウド機能を作成するリージョンを選択します。

一度もこの関数を呼び出したことがない場合、このエラーがポップアップ表示される:

エラーのリンクにアクセスし、Cloud Function APIを有効にしてください:

Serverlessネットワークエンドポイントページに戻り、エンドポイントの名前、ファンクションがあるリージョンを設定し、Cloud Runを選択する(紛らわしいかもしれないが、Cloud Functionsは現在Cloud Run Functionsと呼ばれ、同じ基礎技術を使用している)。
機能を選択し、「作成」をクリックする。

バックエンドのページでは、Cloud CDNキャッシュの設定を行うことができます:
期間(スクリプトの54行目から1時間)またはそれ以上の期間、レスポンスをキャッシュするようにCDNを設定できます。
CDNはウォームキャッシュを使用し、頻繁にリクエストされるコンテンツだけがCDNのキャッシュに保存されることを強調したい。コンテンツに1年間のキャッシュを設定しても、コンテンツへの頻繁なリクエストがない場合、しばらくするとCDNがオリジン(機能)からコンテンツを引き出すことが予想される。

ロギング機能(上の矢印)をご覧ください。デバッグや使用状況の追跡には最適ですが、コストもかかります(1TBのログで512ドル)。
多くのリクエストを生成する場合、サンプルレートを 0.01に設定することで、 100リクエストごとに1リクエストをログに記録することができます。
セキュリティーまでスクロールしてみよう:
デフォルトでは、Googleはバックエンドのウェブ・アプリケーション・ファイアウォール(WAF)であるCloud Armorを有効にしているが、追加コストが かかるし、これはデモなので、Cloud Armorバックエンド・セキュリティ・ポリシーをクリックして「なし」に変更して無効にする。

次のステップはCreate をクリックし、ロードバランサーのダッシュボードでもう一度Createをクリックします。
注:GCPでロードバランサーを作成・更新すると、伝播に最大15分かかることがあります。
ロードバランサーの準備ができたら、ロードバランサーの名前をクリックすると、生成されたIPが表示される:

このIPにアクセスし、画像の名前と高さと幅を指定する:
http://34.49.21.153/?image=nasdaq.jpg&size=500x600
その結果:6.5MBのファイルではなく、63KBの小さなリサイズされた画像が送られてきた。

私の仕事は、お客様にクラウドの使い方をご案内することです。ぜひdoit.com/servicesをご覧ください。


