このページの内容は Apigee と Apigee ハイブリッドに該当します。
Apigee Edge のドキュメントを表示します。
このドキュメントでは、Apigee を使用して API プロキシを開発するための一連のベスト プラクティスについて説明します。
ここでは、設計、コーディング、ポリシーの使用、モニタリング、デバッグについて取り上げます。記載されている情報は、成功を収めた API プログラムを Apigee と協力して実装してきたデベロッパーによる経験の集積です。これは随時更新されるドキュメントです。
ここに示すガイドラインに加えて、アンチパターンの概要も役に立ちます。
開発基準
コメントとドキュメント
ProxyEndpoint
やTargetEndpoint
の構成に、インライン コメントを残してください。特に、Flow の基礎となる機能を表すためにポリシー ファイル名だけでは不十分な場合は、コメントを使用することで Flow のわかりやすさが向上します。- 有意義なコメントを残してください。露骨なコメントは避けてください。
- インデント、スペースの挿入、縦方向の配置などに一貫性をもたせます。
フレームワーク スタイルのコーディング
フレームワークスタイルのコーディングでは、API プロキシ リソースをバージョン管理システムに保存して、ローカル開発環境で再利用します。たとえば、ポリシーを再利用するには、ポリシーをソース管理に保存して、デベロッパーがそれを同期して各自のプロキシ開発環境で使用できるようにします。
- DRY(繰返しを避けること)を実践するには、できる限り、再利用可能な専用の関数をポリシー構成やスクリプトに実装します。たとえば、リクエスト メッセージからクエリ パラメータを抽出する専用のポリシーを
ExtractVariables.ExtractRequestParameters
とし、 - 未使用のポリシーやリソース(JavaScript、Java、XSLT など)、特にインポートやデプロイの処理速度が低下する可能性がある大規模なリソースを API プロキシからクリーンアップします。
命名規則
- ポリシーの
name
属性と XML ポリシー ファイル名を同じにする必要があります。 - Script ポリシーと、ServiceCallout ポリシーのポリシー
name
属性、リソース ファイルの名前が同じである必要があります。 DisplayName
は、該当する API プロキシの使用経験がまったくない担当者が理解できるように、ポリシーの機能を正確に記述する必要があります。- 機能に応じてポリシーに名前を付けます。Apigee では、ポリシーに一貫した命名規則を設定することをおすすめします。たとえば、短い接頭辞の後に、ダッシュで区切った一連のわかりやすい単語を続けます。たとえば、AssignMessage ポリシーの場合は
AM-xxx
です。apigeelint ツールもご覧ください。 - リソース ファイルに適切な拡張子(JavaScript ファイルの場合は
.js
、Python ファイルの場合には.py
、Java JAR ファイルの場合には.jar
)を使用します。 - 変数名は一貫したスタイルにする必要があります。camelCase や under_score など、特定のスタイルを選択したら、API プロキシ全体でそれを使用します。
- 可能であれば、変数接頭辞を使用して、目的に基づいて変数を整理します(例:
Consumer.username
、Consumer.password
)。
API プロキシの開発
初期設計での考慮事項
- RESTful API 設計のガイダンスについては、電子書籍の Web API Design: The Missing Link をダウンロードしてください。
- API プロキシを構築するために、できる限り Apigee のポリシーや機能を活用してください。 すべてのプロキシ ロジックを JavaScript、Java、または Python のリソースでコーディングすることは避けてください。
- Flow は整理して構築します。同じ PreFlow や Postflow に条件を複数アタッチするのではなく、条件が 1 つだけの Flow を複数使用してください。
- フェイルセーフとして、ProxyEndpoint の BasePath を
/
に設定してデフォルトの API プロキシを作成します。これを使用することで、ベース API リクエストをデベロッパー サイトにリダイレクトすることや、カスタム レスポンスを返すこと、またはデフォルトのmessaging.adaptors.http.flow.ApplicationNotFound
を返すことより有益な別のアクションを実行できます。 - 最適なパフォーマンスを得るため、1 つの Apigee 環境または環境グループで使用する API プロキシ ベースパスは 3,000 個以下にすることを推奨します。この推奨値を超えると、新規および既存のすべての API プロキシのデプロイでレイテンシが増加する可能性があります。
- TargetServer リソースを使用して、TargetEndpoint 構成を具体的な URL から切り離し、複数の環境にわたる促進をサポートします。
バックエンド サーバー間の負荷分散をご覧ください。 - RouteRule が複数ある場合は「デフォルト」、つまり無条件の RouteRule として RouteRule を 1 つ作成します。デフォルトの RouteRule が条件付きルートリストの最後に定義されていることを確認してください。RouteRules は ProxyEndpoint でトップダウンで評価されます。API プロキシ構成リファレンスをご覧ください。
- API プロキシのバンドルサイズ: API プロキシ バンドルが 15 MB を超えないようにしてください。
- API のバージョニング: API のバージョニングに関する Apigee の考えと推奨事項については、電子書籍『ウェブ API 設計: ミッシング リンク』のバージョニングをご覧ください。
CORS の有効化
API を公開する前に、CORS ポリシーを ProxyEndpoint の PreFlowのリクエスト に追加して、クライアント側のクロスオリジン リクエストをサポートする必要があります。
CORS(クロスオリジン リソース シェアリング)は、ウェブページで実行される JavaScript XMLHttpRequest(XHR)呼び出しがオリジン以外のドメインのリソースとやり取りできるようにする標準メカニズムです。CORS は、すべてのブラウザで適用されている同一オリジン ポリシーに実装される一般的なソリューションです。たとえば、ブラウザで実行している JavaScript コードから Twitter API への XHR 呼び出しを行う場合、この呼び出しは失敗します。その理由は、ブラウザに該当ページを提供しているドメインが、Twitter API を提供しているドメインと同じではないことです。CORS はこの問題を解消するため、サーバーがクロスオリジンでリソースを共有したい場合に、サーバーが「オプトイン」できる(承諾が得られる)ようにします。
API を公開する前に CORS を API プロキシで有効にする方法については、API プロキシへの CORS サポートの追加をご覧ください。
メッセージ ペイロードのサイズ
Apigee でメモリの問題を回避するために、メッセージ ペイロードのサイズが 10 MB に制限されます。このサイズを超えると、protocol.http.TooBigBody
エラーが発生します。
この問題は、Apigee プロキシで大きなペイロードをリクエストまたは返す際のエラーでも説明されています。
Apigee で大きなメッセージ サイズを扱う場合に推奨する方法は次のとおりです。
- リクエストとレスポンスをストリーミングします。ストリーミングすると、ポリシーがメッセージのコンテンツにアクセスできなくなります。リクエストとレスポンスのストリーミングをご覧ください。
障害の処理
- すべての障害処理に FaultRules を使用します(RaiseFault ポリシーを使用して、メッセージ Flow を停止して処理を FaultRules Flow に送信します)。
- FaultRules Flow 内では、RaiseFault ポリシーではなく AssignMessage ポリシーを使用して障害レスポンスをビルドします。発生した障害の種類に応じて、AssignMessage ポリシーを条件付きで実行します。
- デフォルトの「キャッチオール」障害ハンドラを必ず含めて、システムが生成する障害を顧客定義の障害レスポンス形式にマッピングできるようにしてください。
- 可能であれば、企業やプロジェクトで使用できる標準形式に沿って障害レスポンスを作成します。
- エラー状態に対する解決策を提案する、人が読める形式の意味のあるエラー メッセージを使用します。
障害の処理をご覧ください。
永続
Key-Value マップ
- Key-Value マップは限られたデータセットのみに使用します。長期的なデータストアのためには設計されていません。
- この情報は Cassandra データベースに保存されるため、Key-Value マップを使用する際にはパフォーマンスを考慮してください。
KeyValueMapOperations ポリシーをご覧ください。
レスポンスのキャッシュ保存
- レスポンスに成功しなかった場合、またはリクエストが GET ではなかった場合は、レスポンス キャッシュへの挿入はしないでください。作成、更新、削除はキャッシュしません。
<SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
- キャッシュには決まった 1 種類のコンテンツ(XML や JSON など)を挿入します。responseCache エントリを取得したら、JSONtoXML や XMLToJSON で必要な種類のコンテンツに変換します。これにより、データの二重、三重などの格納を避けられます。
- キャッシュキーがキャッシュ要件を満たしていることを確認します。多くの場合、
request.querystring
を一意の識別子として使用できます。 - 明らかな必要性がない限り、API キー(
client_id
)をキャッシュキーに含めないでください。一般に、キーだけでセキュリティ保護されている API は、与えられたリクエストに対し、すべてのクライアントに同じデータを返します。API キーに基づいて多数のエントリに同じ値を格納するのは非効率的です。 - 適切なキャッシュ有効期間を設けて、ダーティリードを防ぎます。
- 可能であれば、キャッシュへの挿入に関するレスポンス キャッシュ ポリシーが、ProxyEndpoint レスポンス PostFlow のできるだけ遅い段階で実行されるようにしてください。言い換えると、JavaScript ベースのメディエーションや、JSON と XML の間の変換など、変換手順やメディエーション手順の後に実行します。メディエーション後のデータをキャッシュに保存することで、キャッシュ データを取得するたびにメディエーション手順を実行するというパフォーマンス コストを回避できます。
メディエーションの結果がリクエストに応じて異なる場合は、メディエーションされていないデータをキャッシュに保存することもできます。
- キャッシュ エントリをルックアップするレスポンス キャッシュ ポリシーを、ProxyEndpoint リクエスト PreFlow で機能するようにしてください。また、キャッシュキー生成を除き、キャッシュ エントリを返す前にロジックを実装しすぎないようにします。そうしないと、キャッシュに保存するメリットが大幅に減ります。
- 一般に、レスポンス キャッシュ ルックアップは常にクライアント リクエストにできるだけ近づけます。逆に、レスポンス キャッシュの挿入は、クライアント レスポンスにできるだけ近づけます。
- プロキシで複数の異なるレスポンス キャッシュ ポリシーを使用する場合は、以下のガイドラインに従って、それぞれの個別の動作を確認してください。
- 相互に排他的な条件に基づいて各ポリシーを実行します。このようにすると、複数のレスポンス キャッシュ ポリシーのうち 1 つのみが確実に実行されるようになります。
- レスポンス キャッシュ ポリシーごとに異なるキャッシュ リソースを定義します。キャッシュ リソースは、ポリシーの
<CacheResource>
要素で指定します。
Response Cache ポリシーをご覧ください。
ポリシーとカスタムコード
ポリシーか、カスタムコードか
- (できる限り)組み込みポリシーを優先して使用します。Apigee ポリシーは強化され、最適化されており、サポート対象です。たとえば、ペイロードの作成、ペイロード(XPath、JSONPath)からの情報の抽出などには、JavaScript ではなく標準の AssignMessage ポリシーや ExtractVariables ポリシーを使用してください。
- JavaScript は Python や Java よりも推奨されます。ただし、パフォーマンスが最優先であれば、JavaScript ではなく Java を使用してください。
JavaScript
- JavaScript は、Apigee ポリシーよりわかりやすい場合に使用します(たとえば、さまざまな URI の組み合わせに
target.url
を設定する場合など)。 - JSON オブジェクトを介した反復処理や Base64 エンコード / デコードなどの複雑なペイロード解析。
- JavaScript ポリシーには時間制限があるため、無限ループはブロックされます。
- 常に JavaScript ステップを使用して、ファイルを
jsc
リソース フォルダに配置します。 JavaScript ポリシータイプでは、デプロイ時にコードがプリコンパイルされます。
Java
- パフォーマンスが最優先の場合、またはロジックを JavaScript では実装できない場合は Java を使用します。
- Java ソースファイルをソースコード追跡の対象に含めます。
API プロキシでの Java の使用については、JavaCallout ポリシーをご覧ください。
Python
- どうしても必要な場合を除いて、Python は使用しないでください。Python スクリプトは実行時に解釈されるため、実行するだけでパフォーマンスのボトルネックが発生することがあります。
スクリプト コールアウト(Java、JavaScript、Python)
- グローバルの try/catch またはそれに相当する機能を使用します。
- 意味のある例外をスローし、適切にキャッチして、障害レスポンスに使用します。
- 早期に例外をスローしてキャッチします。すべての例外を処理するためにグローバル try/catch を使用しないでください。
- 必要に応じて、null や未定義チェックを行います。たとえば、オプションのフロー変数を取得する場合には、このチェックを行います。
- スクリプト コールアウト内で HTTP/S リクエストを行うことを避けます。代わりに、ServiceCallout ポリシーを使用して、接続を適切に処理します。
JavaScript
- API プラットフォーム上の JavaScript では、E4X を介して XML がサポートされます。
JavaScript オブジェクト モデルをご覧ください。
Java
- メッセージ ペイロードにアクセスする際には、
context.getMessage()
とcontext.getResponseMessage
またはcontext.getRequestMessage
を使用してみてください。これにより、リクエスト フローとレスポンス フローの両方でペイロードを取得できます。 - ライブラリを Apigee の組織または環境に読み込みます。JAR ファイルにはライブラリを含めないでください。これにより、バンドルサイズが小さくなり、他の JAR ファイルで同じライブラリ リポジトリにアクセスできるようになります。
- JAR ファイルは、API プロキシ リソース フォルダに格納するのではなく、Apigee リソース API を使用してインポートします。これにより、デプロイに要する時間が短縮され、同じ JAR ファイルを複数の API プロキシが参照できるようになります。もう一つのメリットは、クラスローダーを分離できることです。
- Java をリソースの処理(スレッドプールの作成や管理など)に使用しないでください。
Python
- 意味のある例外をスローし、Apigee 障害レスポンスで使用するために適切にキャッチします。
Python Script ポリシーをご覧ください。
ServiceCallouts
- プロキシ チェーンの使用については、有効なユースケースが数多くあります。プロキシ チェーンでは、ある API プロキシのサービス コールアウトを使用して、別の API プロキシを呼び出します。プロキシ チェーンを使用する場合は、同じ API プロキシに戻ってくる「無限ループ」の再帰コールアウトを確実に避けてください。
同じ組織と環境内にあるプロキシ間で接続している場合は、不要なネットワーク オーバーヘッドを回避するローカル接続の実装について、チェーンによる API プロキシの接続をご覧ください。
- AssignMessage ポリシーを使用して ServiceCallout リクエスト メッセージを構築し、リクエスト オブジェクトをメッセージ変数に代入します(これには、リクエスト ペイロード、パス、メソッドの設定が含まれます)。
- ポリシー内で構成された URL にはプロトコル仕様が必要です。つまり、URL のプロトコル部分(
https://
など)を変数で指定することはできません。また、URL のドメイン部分と URL の残りの部分では、別々の変数を使用する必要があります。例:https://example.com
- ServiceCallout のレスポンス オブジェクトは別個のメッセージ変数に格納します。そのうえでメッセージ変数を解析し、元のメッセージ ペイロードは他のポリシーでの使用に備えて、そのままにします。
Service Callout ポリシーをご覧ください。
エンティティへのアクセス
AccessEntity ポリシー
- パフォーマンスを向上させるには、アプリ名ではなく
uuid
でアプリを検索します。
AccessEntity ポリシーをご覧ください。
ロギング
- バンドル間、同じバンドル内で共通の Syslog ポリシーを使用します。これにより、一貫したロギング形式が維持されます。
Message Logging ポリシーをご覧ください。
モニタリング
クラウドのお客様は、Apigee の個々のコンポーネント(Router、Message Processor など)を確認する必要はありません。Apigee のグローバル オペレーション チームは、すべてのコンポーネント、API ヘルスチェック、お客様によるヘルスチェック リクエストを徹底的にモニタリングしています。
Apigee Analytics
Analytics では、エラーの割合が測定されるため、重要ではない API モニタリングを行えます。
Analytics ダッシュボードをご覧ください。
デバッグ
Apigee UI のトレースツールは、API の開発または本番環境のオペレーション中にランタイム API の問題をデバッグするために役立ちます。
Debug ツールの使用をご覧ください。
セキュリティ
- テスト環境へのアクセスを制限するには、IP アドレス制限ポリシーを使用します。開発マシンまたは開発環境の IP アドレスへのアクセスを許可し、他のすべての IP アドレスを禁止します。AccessControl ポリシーをご覧ください。
- 本番環境にデプロイされた API プロキシには、コンテンツ保護ポリシー(JSON または XML)を常に適用します。JSONThreatProtection ポリシーをご覧ください。
- その他のセキュリティに関するベスト プラクティスについては、次のトピックをご覧ください。
API プロキシのカスタム ロジック
API プロキシを構築する際の一般的な要件は、リクエストやレスポンスを処理するためのロジックを組み込むことです。事前に定義された一連のステップ、アクション、ポリシー(トークンの確認、割り当ての適用、キャッシュ オブジェクトによるレスポンスなど)から多くの要件が満たすことができる一方で、プログラマビリティへのアクセスが必要になることがあります。たとえば、リクエスト内のキーに基づいてルーティング テーブルからロケーション(エンドポイント)を検索したり、ターゲット エンドポイントやカスタム/独自の認証方法を動的に適用したりします。
Apigee では、デベロッパーがこのようなカスタム ロジックを処理するためのオプションが複数用意されています。このドキュメントでは、これらのオプションと、それらを使用するタイミングについて説明します。
ポリシー | ポリシーのユースケース |
---|---|
JavaScript と PythonScript |
使用するタイミング:
使用できないケース:
ベスト プラクティス: JavaScript は優れたパフォーマンスを実現するため、PythonScript よりも JavaScript が推奨されます。 |
JavaCallout |
使用するタイミング:
使用できないケース:
|
ExternalCallout |
使用するタイミング:
使用しない場合:
|
ServiceCallout |
使用するタイミング:
使用しない場合:
|
まとめ
- ロジックが単純であるか自明である場合、JavaScript(推奨)または PythonScript を使用します。
- インライン ロジックで JavaScript や PythonScript よりも高いパフォーマンスが必要な場合は、JavaCallout を使用します。
- ロジックを外部化する必要がある場合は、ExternalCallout を使用します。
- 外部実装がすでに存在する場合やデベロッパーがすでに REST に精通している場合は、ServiceCallout を使用します。
次の図に、このプロセスを示します。