PHP バージョン 5.5 はコミュニティでサポートを終了したため、新しいアプリでは PHP 7 ランタイムを使用することを強くおすすめします。

リクエストの処理方法

リージョン ID

REGION_ID は、アプリの作成時に選択したリージョンに基づいて Google が割り当てる省略形のコードです。一部のリージョン ID は、一般的に使用されている国や州のコードと類似しているように見える場合がありますが、このコードは国または州に対応するものではありません。既存のアプリでは省略可能ですが、まもなく、新しいアプリのすべてにおいて App Engine の URL に REGION_ID.r を含めることが必須となる予定です。

移行がスムーズに行われるように、リージョン ID を使用するよう App Engine を徐々に更新しています。Google Cloud プロジェクトがまだ更新されていない場合、アプリにリージョン ID が表示されません。ID は既存のアプリでは省略可能なため、リージョン ID が既存のアプリで使用可能になったときに、URL の更新や他の変更を行う必要はありません。

詳しくは、リージョン ID をご覧ください。

このドキュメントでは、App Engine アプリケーションがリクエストを受信してレスポンスを送信する方法を説明します。詳細については、リクエストのヘッダーとレスポンスのリファレンスをご覧ください。

アプリケーションでサービスを使用している場合は、特定のサービスまたはそのサービスの特定のバージョンへのリクエストを指定できます。サービスのアドレス指定の方法については、リクエストのルーティング方法をご覧ください。

リクエストの処理

アプリケーションは、ウェブサーバーの起動とリクエストの処理を行う役割を果たします。 使用する開発言語に対応している任意のウェブ フレームワークを使用できます。

App Engine はアプリケーションの複数のインスタンスを実行します。各インスタンスには、リクエストを処理するウェブサーバーがそれぞれ割り当てられます。リクエストがルーティングされるインスタンスは任意に決まるため、同じユーザーから連続して送信されたリクエストが同じインスタンスに届くとは限りません。インスタンスは、複数のリクエストを同時に処理できます。インスタンスの数は、トラフィック量の変化に応じて自動的に調整されます。また、app.yaml ファイルの max_concurrent_requests 要素を設定すると、インスタンスが同時に処理できるリクエストの数を変更できます。

サーバーでは、リクエストの URL とアプリの app.yaml 構成ファイル内で指定された URL パターンを比較して、実行する PHP ハンドラ スクリプトを決定します。続いて、リクエストのデータが入力されたスクリプトを実行します。サーバーによって、環境変数と標準入力ストリームにリクエストのデータが配置されます。このスクリプトでは、リクエストに適切なアクションを実行してから、レスポンスを準備して標準出力ストリームに配置します。

すべての HTTP リクエストに対してメッセージ「Hello World!」で応答する PHP スクリプトの例を以下に示します

<?php

echo 'Hello, World!';

割り当てと上限

App Engine は、トラフィックが増加すると、自動的にアプリケーションにリソースを割り当てます。ただし、次のような制限があります。

  • App Engine は、1 秒未満でリクエストに応答するレイテンシが短いアプリケーション向けに、自動スケーリングのための容量を予約しています。多くのリクエストで 1 件につき 1 秒を超えるなど、レイテンシが大きく、スループットが高いアプリケーションでは、シルバー、ゴールド、またはプラチナのサポートが必要です。これらのレベルのサポートを契約済みの場合は、サポート担当者に連絡してスループットの上限を引き上げることができます。

  • また、CPU の制約を大きく受けるアプリケーションでも、同じサーバー上の他のアプリケーションとリソースを効率的に共有するために、追加のレイテンシが生じる場合があります。静的ファイルへのリクエストには、このようなレイテンシの制限は適用されません。

アプリケーションが受信する各リクエストには、リクエスト数の上限が適用されます。リクエストへのレスポンスとして送信されるデータは、送信帯域幅(課金対象)の上限対象としてカウントされます。

HTTP リクエストと HTTPS(セキュア)リクエストのどちらにも、リクエスト数受信帯域幅(課金対象)送信帯域幅(課金対象)の上限が適用されます。Cloud Console の割り当ての詳細ページでは、参考のために、[安全なリクエスト数]、[安全な受信帯域幅]、[安全な送信帯域幅] の値もそれぞれ報告されます。これらの値は、HTTPS リクエストにのみ適用されます。詳細については、割り当てページをご覧ください。

リクエスト ハンドラの使用には、それぞれ次の上限や時間制限が適用されます。

上限と時間制限
リクエスト サイズ 32 MB
レスポンス サイズ 32 MB
リクエスト タイムアウト アプリが使用するスケーリングのタイプに依存
最大合計ファイル数(アプリファイルと静的ファイル) 合計 10,000 ファイル
1 ディレクトリあたり 1,000 ファイル
アプリケーション ファイルの最大サイズ 32 MB
静的ファイルの最大サイズ 32 MB
すべてのアプリケーション ファイルと静的ファイルの最大合計サイズ 最初の 1 GB は無料
最初の 1 GB を超えると、以降は 1 GB あたり毎月 $ 0.026

レスポンスに関する上限

動的レスポンスの上限は 32 MB です。スクリプト ハンドラが生成したレスポンスの大きさがこの上限を超える場合は、サーバーから内部サーバーエラー ステータス コード 500 を示す空のレスポンスが返されます。Cloud Storage からデータを返すレスポンスには、この上限が適用されません。

リクエスト ヘッダー

受信した HTTP リクエストには、クライアントから送信された HTTP ヘッダーが含まれています。セキュリティ上の理由から、一部のヘッダーは、アプリケーションに到達する前に中間プロキシによってサニタイズ(リスクのある部分などを削除)または修正されます。

詳細については、リクエスト ヘッダーのリファレンスをご覧ください。

リクエスト期限の指定

App Engine はリクエストの存続時間が短いアプリケーション(通常は数百ミリ秒程度)向けに最適化されています。効率的なアプリは、大部分のリクエストに短時間で応答します。そうでないアプリは、App Engine のインフラストラクチャに合わせて適切にスケールされません。

PHP スクリプトは限られた時間の中でリクエストへのレスポンスを生成して返す必要があります。この制限に達すると、接続ステータス ビットフィールドの TIMEOUT ビットが設定されます。このスクリプトには、長時間実行されているタスクをクリーンアップしてユーザーにレスポンスを返すまでの時間に対する短い別の制限もあります。

この制限時間までにスクリプトからレスポンスが返されないと、ハンドラが終了し、デフォルトのエラー レスポンスが返されます。

レスポンス

App Engine は、$_REQUEST 配列に所定の設定を行ってスクリプトを呼び出し、このスクリプトからの出力をバッファリングします。そしてスクリプトの実行が完了すると、バッファリングされた出力をエンドユーザーに送信します。

生成するレスポンスにはサイズの上限があり、レスポンスはクライアントに返される前に変更される可能性があります。

詳細については、リクエストに対するレスポンスのリファレンスをご覧ください。

レスポンスのストリーミング

App Engine は、レスポンスのストリーミングをサポートしていません。つまり、リクエスト 1 件のデータをチャンクに分けて順に送信することはできません。コードからのデータ全体が前述のように収集されて、単一の HTTP レスポンスとして送信されます。

レスポンスの圧縮

App Engine は、gzip をサポートするクライアントに gzip 圧縮されたコンテンツを最大限配信するように設計されています。コンテンツを圧縮する必要があるかどうかを判断するために、App Engine はリクエストを受信すると次の処理を行います。

  1. リクエスト内の Accept-Encoding ヘッダーと User-Agent ヘッダーの両方を確認して、クライアントが圧縮されたレスポンスを適切に受信できるかどうかを確認します。このアプローチにより、gzip 圧縮されたコンテンツを一般的なブラウザで利用する際に発生する、周知のバグを回避します。

  2. レスポンス ハンドラに構成した Content-Type ヘッダーを表示して、コンテンツを圧縮することが適切であるかどうかを確認します。一般的に、テキストベースのコンテンツ タイプは圧縮に適していますが、バイナリ コンテンツ タイプは適していません。

次の点にご注意ください。

  • クライアントは Accept-EncodingUser-Agent の両方のリクエスト ヘッダーを gzip に設定することにより、テキストベースのコンテンツ タイプの圧縮を強制できます。

  • リクエストで Accept-Encoding ヘッダーに gzip が指定されていない場合、App Engine はレスポンス データを圧縮しません。

  • Google フロントエンドは、App Engine の静的ファイルとディレクトリ ハンドラからのレスポンスをキャッシュに保存します。最初にキャッシュに保存されるレスポンス データのタイプ、レスポンスに指定した Vary ヘッダー、リクエストに含まれるヘッダーなど、さまざまな要因によって、クライアントが圧縮データをリクエストしても圧縮されていないデータを受信する場合があります。また、その逆の場合もあります。詳細については、レスポンスのキャッシュ保存をご覧ください。

レスポンスのキャッシュ保存

Google フロントエンド、場合によってはユーザーのブラウザおよびその他の中間キャッシング プロキシ サーバーは、レスポンスに指定した標準キャッシング ヘッダーの指示に従って、アプリのレスポンスをキャッシュに保存します。これらのレスポンス ヘッダーは、フレームワークを介して、またはコード内で直接指定するか、App Engine の静的ファイルとディレクトリ ハンドラを使用して指定できます。

Google フロントエンドでは、キャッシュキーはリクエストの完全な URL です。

静的コンテンツのキャッシュ保存

静的コンテンツが公開された場合にクライアントが直ちに受信できるように、css/v1/styles.css などのバージョニングされたディレクトリから静的コンテンツを配信することをおすすめします。Google フロントエンドは、キャッシュが期限切れになるまで、キャッシュの検証(更新されたコンテンツの確認)を行いません。キャッシュが期限切れになった後でも、リクエスト URL のコンテンツが変更されるまでキャッシュは更新されません。

app.yaml で設定できる次のレスポンス ヘッダーは、Google フロントエンドがコンテンツをキャッシュに保存する方法とタイミングに影響します。

  • Google フロントエンドがコンテンツをキャッシュに保存するように設定するには、Cache-Controlpublic に設定する必要があります。app.yaml でこのヘッダーを設定しなかった場合、App Engine は静的ファイルまたはディレクトリ ハンドラによって処理されるすべてのレスポンスにこのヘッダーを自動的に追加します。詳細については、追加または置換されるヘッダーをご覧ください。

  • Vary: リクエストで送信されるヘッダーに基づいて、URL に対してさまざまなレスポンスがキャッシュから返されるようにするには、AcceptAccept-EncodingOriginX-Origin のうち 1 つ以上を Vary レスポンス ヘッダーに設定します。

    カーディナリティが高い可能性があるため、他の Vary 値についてはデータがキャッシュに保存されません。

    例:

    1. 次のレスポンス ヘッダーを指定します。

      Vary: Accept-Encoding

    2. アプリは Accept-Encoding: gzip ヘッダーを含むリクエストを受信します。App Engine は圧縮されたレスポンスを返し、Google フロントエンドはレスポンス データの gzip 圧縮されたバージョンをキャッシュに保存します。この URL に対する Accept-Encoding: gzip ヘッダーを含む後続のすべてのリクエストは、キャッシュが無効になる(キャッシュの有効期限が切れた後にコンテンツが変更されたことによる)までキャッシュから gzip 圧縮されたデータを受信します。

    3. アプリは、Accept-Encoding ヘッダーを含まないリクエストを受信します。App Engine は圧縮されていないレスポンスを返し、Google フロントエンドはレスポンス データの非圧縮バージョンをキャッシュに保存します。この URL に対する Accept-Encoding ヘッダーを含まない後続のすべてのリクエストは、キャッシュが無効になるまでキャッシュから圧縮されたデータを受信します。

    Vary レスポンス ヘッダーを指定しない場合、Google フロントエンドは URL に対して 1 つのキャッシュ エントリを作成し、作成したエントリをリクエストのヘッダーにかかわらず、すべてのリクエストで使用します。例:

    1. Vary: Accept-Encoding レスポンス ヘッダーが指定されていません。
    2. リクエストには Accept-Encoding: gzip ヘッダーが含まれ、レスポンス データの gzip 圧縮されたバージョンがキャッシュに保存されます。
    3. 2 番目のリクエストには Accept-Encoding: gzip ヘッダーが含まれていません。ただし、キャッシュにはレスポンス データの gzip 圧縮されたバージョンが含まれているため、クライアントが非圧縮データをリクエストした場合でも、レスポンスは gzip 圧縮されます。

リクエスト内のヘッダーもキャッシュ保存に影響します。

  • リクエストに Authorization ヘッダーが含まれている場合、コンテンツは Google フロントエンドによってキャッシュに保存されません。

キャッシュの有効期限

デフォルトでは、App Engine の静的ファイルとディレクトリ ハンドラによってレスポンスに追加されるキャッシュ ヘッダーは、クライアントとウェブプロキシ(Google フロントエンドなど)が 10 分後にキャッシュを期限切れにするよう指示します。

任意の有効期限が設定された状態でファイルが転送された場合、一般的にユーザーは自身のブラウザ キャッシュを消去しても、ウェブプロキシのキャッシュからファイルを消去することはできません。アプリの新しいバージョンを再度デプロイしても、キャッシュはリセットされません。そのため、静的ファイルを変更する予定がある場合は、短期間(1 時間未満)の有効期限を設定するようにしてください。ほとんどの場合、デフォルトの 10 分間の有効期限で十分です。

app.yaml ファイルで default_expiration 要素を指定すると、すべての静的ファイルとディレクトリ ハンドラのデフォルトの有効期限を変更できます。個別のハンドラに特定の有効期限を設定するには、app.yaml ファイルのハンドラ要素内で expiration 要素を指定します。

有効期限要素の時間で指定する値は、Cache-ControlExpires の HTTP レスポンス ヘッダーの設定に使用されます。

アプリ キャッシング

PHP のランタイム環境には、PHP の中間コードをキャッシュに保存してアプリケーションのレスポンス時間を大幅に改善できる OPcache が用意されています。OPcache によるキャッシングを無効にするには、アプリケーションの php.ini ファイルで opcache.enabled = "0" を設定します。

ログ

App Engine ウェブサーバーは、ウェブ リクエストへのレスポンスとしてハンドラ スクリプトが標準出力ストリームに書き込むすべての内容をキャプチャします。また、ハンドラ スクリプトが標準エラー ストリームに書き込むすべての内容もキャプチャし、ログデータとして保存します。アプリケーションのログデータは、Cloud Logging を使用して、Cloud Console で表示できます。

App Engine PHP ランタイム環境では、Logs API を呼び出す PHP の組み込み syslog() 関数を使用して、アプリケーションからの任意のメッセージをログに記録できます。

環境

HTTPS 接続の強制

セキュリティ上の理由から、すべてのアプリケーションは、https で接続するようクライアントに促すべきです。特定のページまたはドメイン全体で http よりも https を優先するようにブラウザに指示するには、レスポンスに Strict-Transport-Security ヘッダーを設定します。例:

Strict-Transport-Security: max-age=31536000; includeSubDomains
アプリによって配信される静的コンテンツにこのヘッダーを設定するには、アプリの静的ファイルとディレクトリ ハンドラにヘッダーを追加します。