サーバー側の Web 階層キャッシング
Commerce Cloud アプリケーション層コンポーネントの 1 つは、SCAPI リクエストの Web 階層キャッシングを実行します。これは、さまざまな API ファミリーへの GET リクエストに影響を与えます。
このサーバー側のキャッシングメカニズムは、リクエストが Commerce Cloud のサーバー側アプリケーション層に到達した後でのみ使用されます。別のキャッシングメカニズムが設置されている場合は (たとえば、クライアント側)、そのメカニズムは引き続き独立して使用されます。ストアフロント実装のフロントエンドまたはクライアント側で複数のキャッシング層を扱う場合は、これを考慮する必要があります。
ストアフロントとは異なり、SCAPI で使用されるのはサーバー側の Web 階層キャッシュのみであり、eCDN のエッジキャッシュは SCAPI にはまったく適用されません。
次の API の GET リクエストに対するレスポンスはキャッシュされます。
- /product/shopper-products/v1/organizations/{org-id}/categories/{id}
- /product/shopper-products/v1/organizations/{org-id}/categories
- /product/shopper-products/v1/organizations/{org-id}/products/{id}
- /product/shopper-products/v1/organizations/{org-id}/products
- /search/shopper-search/v1/organizations/{org-id}/product-search
- /search/shopper-search/v1/organizations/{org-id}/search-suggestions
- /pricing/shopper-promotions/v1/organizations/{org-id}/promotions/campaigns
- /pricing/shopper-promotions/v1/organizations/{org-id}/promotions/campaigns
- /site/shopper-seo/v1/organizations/{org-id}/url-mapping
- /store/shopper-stores/v1/organizations/{org-id}/stores
- /configuration/preferences/v1/organizations/{org-id}/site-custom-preferences?{siteId}
- /configuration/preferences/v1/organizations/{org-id}/global-custom-preferences
- /experience/shopper-experience/v1/organizations/{org-id}/pages
- /experience/shopper-experience/v1/organizations/{org-id}/pages/{pageId}
Shopper Experience API のキャッシュの詳細については、Page Designer ドキュメントを参照してください。
動的コンテンツのページキャッシュは、特定のサイトで有効にする必要があります。
これを行うには、Business Manager で、管理 > サイト > サイトの管理 > サイト名 - キャッシュの順に移動し、その後「ページキャッシングを有効にする」を選択します。
キャッシュエントリの有効期間、ならびにレスポンスがパーソナライズされるかどうかは、API によって決まります。また、API で展開 (expansion) が利用できる場合は、選択された展開によっても決まります。
| API 名 | 展開 | キャッシュの TTL (秒単位) (デフォルト) | パーソナライズ済み (デフォルト) |
|---|---|---|---|
| Categories | 該当なし | 86400 | いいえ |
| Products | availability | 60 | いいえ |
| bundled_products | 86400 | いいえ | |
| images | 86400 | いいえ | |
| links | 86400 | いいえ | |
| options | 86400 | いいえ | |
| page_meta_tags | 86400 | いいえ | |
| prices | 900 | はい | |
| promotions | 900 | はい | |
| recommendations | 86400 | いいえ | |
| set_products | 86400 | いいえ | |
| shipping_methods | 86400 | いいえ | |
| variations | 86400 | いいえ | |
| なし | 86400 | いいえ | |
| Product Search | availability | 60 | いいえ |
| custom_properties | 86400 | いいえ | |
| images | 900 | いいえ | |
| page_meta_tags | 86400 | いいえ | |
| prices | 900 | はい | |
| promotions | 900 | はい | |
| represented_products | 900 | いいえ | |
| variations | 900 | いいえ | |
| なし | 900 | いいえ | |
| Search Suggestions | 該当なし | 900 | いいえ |
| Promotions | 該当なし | 3600 | いいえ |
| Campaigns | 該当なし | 3600 | いいえ |
| SEO Url Mapping | 該当なし | 43200 | いいえ |
| Stores | 該当なし | 86400 | いいえ |
| Preferences (サイト) | 300 | いいえ | |
| Preferences (グローバル) | 300 | いいえ |
すべての展開の中で最も短い TTL によって、キャッシュエントリの有効期間が決まります。リクエストされた展開の少なくとも 1 つが「パーソナライズ済み」としてマークされている場合、レスポンス全体がパーソナライズされているとみなされます。
キャッシュヒット率は、product エンドポイントと product-search エンドポイントに対して選択した展開によって大きく影響を受けます。たとえば、商品 API へのリクエストに「availability」展開が含まれている場合、キャッシュエントリはデフォルトで 60 秒間のみ保存されます。expand パラメーターが指定されていない場合は、すべての展開が選択されていると見なされます。
例 1
/product/shopper-products/v1/organizations/{org-id}/products?ids=product1,product2 のリクエストは 30 分ごとに行われます。expand パラメーターが指定されていないため、すべての展開が適用され、その中でも最も短い TTL は「availability」の 60 秒です。その結果、次の同一のリクエストが行われる前にキャッシュエントリの有効期限が切れるため、キャッシュヒット率はゼロのままになる可能性があります。
例 2
/product/shopper-products/v1/organizations/{org-id}/products?ids=product1,product2&expand=images,links,optionsのリクエストは 1 時間ごとに行われます。指定された展開の中で最も短い TTL は 86400 秒 (24 時間) であるため、キャッシュヒット率は高くなることが予想されます。
特定の展開ではキャッシュエントリの有効期間は非常に短いため、必要な展開のみがリクエストに含まれていることを確認するようお勧めします。たとえば、Products API と Product Search API へのリクエストに「availability」の展開を不必要に含めると、キャッシュヒット率が大幅に低下し、リクエストの全体的なパフォーマンスに悪影響を及ぼします。expand パラメーターが指定されていない場合は、すべての展開が選択されていると見なされます。
リソースに対してパーソナライゼーションが有効になっている場合、URL 文字列に加えて、次の情報がキャッシュキーの一部になります。
- アクティブなプロモーションの完全なセット。
- アクティブな商品の並べ替えルールの完全なセット。
- 適用可能な価格表の完全なセット。
- アクティブな A/B テストグループの完全なセット。
キャッシュはさまざまなレスポンスのバリエーションをキャッシュに保存し、この追加情報に基づいて正しいバージョンを API ユーザーに配信します。
2 人の買い物客が同じ商品 API (つまり、同じ URL) にアクセスする場合を考えてみましょう。この場合、買い物客 A はプロモーション X の対象となり、買い物客 B はプロモーション Y の対象となります。同じ商品 (URL は変更なし) が 2 回キャッシュされます。その後、プロモーション X の買い物客全員に、プロモーション Y の買い物客と同じキャッシュエントリが提供されます。このシナリオでは、価格表とプロモーションの数によっては、商品の価格にかかわらず、キャッシュエントリの数が大幅に増加する可能性があります。
パーソナライズされたキャッシングは、必要な場合にのみ使用することを検討してください。また、十分な数の買い物客のグループのみを対象としてください。
新しいリクエストに対して、Web 階層はまずキャッシュエントリが存在するかどうかを確認します。キャッシュキーはフックのカスタマイズが呼び出される前に計算されるため、後からフック内で発生する変更は含まれません。
フックロジック内で行われるパーソナライゼーションの変更は、サーバー側の Web 階層キャッシュとは互換性がありません。
キャッシュキーの計算はフックのカスタマイズが実行される前に行われます。つまり、価格表、プロモーション、その他のパーソナライゼーションの詳細を変更するなど、フック内で行われるパーソナライゼーションの変更は、キャッシュキー生成時には考慮されません。
手順ごとの例:
- リクエストの到着: 買い物客が、プロモーション展開を含む商品をリクエストします。
- キャッシュキーの計算: システムは次の情報に基づいてキャッシュキーを計算します。
- URL とクエリパラメーター
- その他のリクエスト関連要素
- 現在アクティブなプロモーション
- 現在適用されている価格表
- 現在の商品の並べ替えルール
- 現在の AB テストグループ
- キャッシュ検索: システムは、このキャッシュキーを使用して既存のキャッシュエントリを検索します。
- キャッシュミスが発生した場合: リクエストはそのまま処理に進みます。
- フックの実行: カスタムフックが呼び出され、パーソナライゼーションの詳細が変更されます。
- レスポンスの生成: 最終レスポンスは、異なるパーソナライゼーションで生成される可能性があります。
- キャッシュへの保存: レスポンスは、パーソナライゼーションの変更を反映した変更後のキャッシュキーとともに保存されます。
手順 2 のキャッシュキーには、手順 5 で行われたパーソナライゼーションの変更が反映されていないため、次の問題が発生します。
- ユーザーに誤ったキャッシュエントリが返される
- キャッシュミスが発生する
- キャッシュミスの頻発により、パフォーマンスが低下する可能性がある
フックロジック内で適用対象の価格表やプロモーションを変更すると、最終的なキャッシュエントリが元のキーと一致しなくなります。その結果、キャッシュヒット率が低下し、パフォーマンスが下がります。フックベースのパーソナライゼーション変更に依存するのではなく、キャッシュキーが計算される前に Shopper Context API を使用してパーソナライゼーション変更を適用してください。
カスタム属性の追加など、レスポンスボディに対する更新の可能性は、キャッシュキーには考慮されません。URL とクエリ文字列が同一の 2 つのリクエストで、条件付きフックロジックのみによって異なるレスポンスが生成されることが想定される場合でも、Web 階層はそのようなリクエストを同一と見なし、キャッシュされたレスポンスを返します。Web 階層キャッシュが正しく動作するようにするには、URL にカスタムクエリパラメーターを追加してください。
以下に例を示します。
条件コードによるレスポンスのカスタマイズは、条件が URL の一部として、つまりカスタムクエリパラメーターとして指定された場合にのみ正しくキャッシュされます。これは、パフォーマンスに影響を与える可能性があるため、必要な場合にのみ行ってください。
B2C Commerce 24.8 では、Shopper Products (買い物客の商品) の getProductエンドポイントと getCategory エンドポイント、および Campaigns (キャンペーン) の getCampaignエンドポイントに対して、「有効期間」と呼ばれる期間を設定できます。有効性は、古くなったコンテンツが提供されないようにするために、サーバー側のキャッシュの有効期限について考慮されます。有効期間を定義する属性は、Valid From (有効期間開始) と Valid To (有効期間終了) です。その他のリソースタイプについては、デフォルトのキャッシュ有効期限が適用されます。
サーバー側のキャッシュの有効期限は、Valid From 属性と Valid To 属性の日付と時刻の値が定義されており、デフォルトのキャッシュの有効期限より前に有効になる場合は、それらの日付と時刻の値を反映するように調整されます。それ以外の場合は、デフォルトの有効期限が適用されます。
複数の SKU など、複数のリソース識別子を含むリクエストの場合、キャッシュの有効期限を計算する際にすべての有効期間が考慮されます。最も早い有効日によって、レスポンスのキャッシュの有効期限が決まります。
たとえば、1 つの商品 SKU を使用するリクエストは、デフォルトで 24 時間キャッシュされているとします (追加の展開はありません。上の表を参照)。デフォルトのキャッシュ有効期限よりも早い Valid To 時間が商品に割り当てられていると仮定すると、キャッシュの有効期限は、より短い Valid To 時間を反映するように再計算されます。

Valid From 時間を使用して商品の発売を将来の日付に設定すると、HTTP 404 レスポンスコードが返されます。HTTP 404 レスポンスも、それぞれの Valid From 値を反映したキャッシュの有効期限を使用してキャッシュされます。その時点でキャッシュの有効期限が切れると、ストアフロントで買い物客が商品を閲覧できるようになります。

Script API には、キャッシュ設定をプログラムで制御するためのオプションが用意されています。
Script API の dw.system.Response#setExpires( milliseconds ) メソッドを使用すると、任意のキャッシュ有効期限のタイムスタンプを設定できます。このメソッドはミリ秒単位のタイムスタンプを受け入れるため、現在のタイムスタンプと必要な「TTL (有効期間)」の合計をパラメーターとして渡す必要があります。
たとえば、カテゴリ API のレスポンスを 1 日ではなく 1 時間のみキャッシュする場合は、次のカスタムコードを使用できます。
キャッシュの TTL は 1 秒以上である必要があり、86,400 秒を超えることはできません。
Script API の dw.system.Response#setVaryBy( String varyBy ) メソッドは、指定されたバリアント識別子を使用してレスポンスをパーソナライズ済みとしてマークします。price_promotion のみがサポートされており、他の値は無効です。
デフォルトでは、prices (価格) の展開と promotions (プロモーション) の展開を使用した商品呼び出し、および prices (価格) の展開を使用した商品検索呼び出しはパーソナライズれています。
現時点では、キャッシュを手動で無効にする方法は 1 つだけで、サイトのページキャッシュ全体を無効にすることです。
Business Manager で、管理 > サイト > サイトの管理 > サイト名 - キャッシュ の順に移動し、キャッシュタブを選択します。「キャッシュの無効化」セクションに、サイトのページキャッシュを無効にするボタンがあります。無効化がトリガーされると、SCAPI レスポンスに関連するキャッシュを含む、サイトのページキャッシュ全体が 15 分以内にクリアされます。
これにより、既存のパイプラインのキャッシュもすべて無効になり、パフォーマンスが一時的に低下する可能性があります。
新しいサーバー側のキャッシュを導入すると、キャッシュされたエンドポイントのレスポンスは常に Cache-Control ヘッダー値の no-cache, no-store, must-revalidate を返します。特にパーソナライズする場合は、SCAPI と Script Controller API の均一な動作を保証するために必要です。
sfdc_cache_status レスポンスヘッダーは、Web 階層キャッシュがリクエストをどのように処理したかを可視化します。
sfdc_cache_status ヘッダーは Web 階層で計算および設定され、次の場合に返されます。
- このページのキャッシュの対象セクションにリストされている Shopper API エンドポイント。
- カスタム API。
sfdc_cache_status ヘッダーは、次のいずれかの値を返します。
| 値 | 説明 | 例 |
|---|---|---|
HIT [M/M] | メインリクエストと、それに関連するすべてのインクルードリクエストが、完全にキャッシュから解決されました。 | HIT [1/1] |
MISS [0/M] | どのリクエストもキャッシュから解決されませんでした。 | MISS [0/1] |
PARTIAL [N/M] | リクエストはキャッシュから部分的に解決されました。N は 0 より大きく、M より小さい値です。 | PARTIAL [2/5] |
[N/M] という表記は、キャッシュ効率を理解するための手掛かりになります。
- M = メインリクエストと、それに関連するすべてのインクルードリクエストを含む、リクエストの合計数。
- N = キャッシュから解決されたリクエストの数。
ほとんどのリクエストではインクルードリクエストが関係しないため、M は通常 1 に等しく、HIT [1/1] と MISS [0/1] が最も一般的な値になります。PARTIAL ステータスは、インクルードリクエストが含まれる場合にのみ表示されます。
たとえば、リクエストにインクルードリクエストが含まれており、レスポンスヘッダーに PARTIAL [3/5] と表示されている場合は、次のことを意味します。
- 合計 5 件のリクエストが行われた (メインリクエスト 1 件+ インクルードリクエスト 4 件)。
- 5 件のリクエストのうち 3 件はキャッシュから提供された。
- 2 件のリクエストでキャッシュミスが発生し、アプリケーションによって処理された。
Web Adapter Cache Key Ignore by Query String (クエリ文字列ごとの Web Adapter のキャッシュキー無視) 機能トグルを使用して、キャッシュキーからクエリパラメーターを除外できます。これは、キャッシュヒット率を高めたい場合に適用されますが、クエリパラメーターがレスポンスにまったく影響しない場合にのみ適用されます。指定したクエリパラメーターは Salesforce Commerce API とコントローラーのキャッシュに影響するため、この機能トグルは注意して使用してください。