メインコンテンツにスキップ
バージョン: 1.x

同期のパフォーマンスとサーバーへの配慮

v1.10.0の新機能

このページでは、WCPOS v1.10.0 で導入された同期エンジンについて説明します。エンジンの動作の仕組みについては、まず同期エンジンの仕組みをご覧ください。

WCPOSのストアの多くは共有PHPホスティング上で動作しています。PHPワーカーはわずかで、RESTリクエストのたびにWordPressのフルブートストラップが走り、セキュリティプラグインがバーストをレート制限します。クライアントが無料だとみなしているリクエストは、ストアフロントの表示を遅くし、レート制限に引っかかり、キャッシャー自身の通信と競合します。しかもその影響は、稼働しているレジとブラウザータブの数だけ倍増します。

v1.10.0の同期エンジンは、これを後付けの課題ではなく設計上の制約として扱います。販売者のホスティングを守ることは、同期エンジンの仕事の一部です。 このページでは、エンジンが従うルールと、その裏付けとなる測定結果を説明します。

4つの基本ルール​

エンジンでスケジュールされるすべての同期動作は、次の4つの不変条件に従います:

  1. コストはカタログの規模ではなく、変更量に応じて増えます。 大量のデータを取得する前に、必ず低コストのダイジェストまたは早期終了できるチェックを行います。変更のない商品50,000件の店舗を同期状態に保つコストは、変更のない商品500件の店舗とほぼ同じです。
  2. 無制限にリクエストを発行しません。 すべてのバックグラウンドレーンに1回の実行あたりのリクエスト上限があり、自動テストで検証されます。大規模な処理は、再開可能なカーソルを使った上限付きのバッチで実行されます。処理を一気に集中させず、スケジュール全体に分散します。
  3. メンテナンスがキャッシャーの邪魔をすることはありません。 レジが販売できる状態にするためのリクエストが先に実行され、整合性の監査やバックグラウンドの事前読み込みは、その後のアイドル時間に実行されます。
  4. 負荷がかかると、まずメンテナンスが後退します。 サーバーが不調のシグナルを出すと、エンジンはキャッシャーに関わる処理に手を付ける前に、自身のバックグラウンド処理を減速させます。

同期がサーバーにかけるコスト​

定常状態のコストは、ストアヘルス → パフォーマンス でデバイスごとに選択する同期プリセットによって決まります。

プリセットチェック間隔1回のリクエストあたりのレコード数1日あたりの想定チェック数
エコ5分25288
バランス(既定)60秒501,440
リアルタイム10秒758,640

どちらのダイヤルも重要ですが、共有ホスティングで実際にコストになるのはたいていページの重さです。レコード数の多いページはサーバーの処理時間を実際に消費し、間隔はそれを掛け算するだけです。最大値である100件のページを使うプリセットはありません。これはカスタムのスライダー(間隔5秒〜5分、レコード数10〜100)でのみ設定できます。

プリセットに加えて、次の仕組みがあります。

  • アイドル時のチェックは低コストです。 エンジンは条件付きリクエストを送信するため、変更がない場合は本文のない304 Not Modifiedが1つ返ります。リクエスト数は1つのままですが、ペイロードがなく、サーバーの処理も最小限です。
  • チェックには±20%のジッターがかかります。 そのため、多数のレジがバーストとして同期することなく、リクエストを分散します。
  • アイドル状態のレジは減衰します。 10分間操作がないと間隔が長くなり、バーコードスキャンを含むあらゆる操作で即座に元に戻ります。
  • バックグラウンドのメンテナンスには上限があります。 差異のない整合性チェックでは、低コストの集計ページを数ページ取得するだけで、詳細データの取得はゼロです。サーバーと一致していることが確認できたバケットは、そのままスキップします。差異が見つかった場合、詳細調査は1回の実行あたり2回までに制限され、連続して実行せず保存済みカーソルから再開します。削除監査全体は1回の実行あたり11リクエスト、ダイジェストの初期化は1回の実行あたり5チャンクに制限されます。これらの上限はコードで宣言され、CIで検証されます。
アプリ内の「1日あたりのリクエスト数」は想定値です

ストアヘルスでは、設定された間隔から1日あたり約N件のリクエストを推定します。これは上限や予測値ではなく、想定されるチェック頻度として扱ってください。±20%のジッターによって実際の件数は増減し、304もリクエストとして数えられます。アイドル時の減衰は、チェック間隔が60秒より短いプリセットにのみ適用されます。デフォルトの「バランス」プリセットがさらに遅くなることはありません。

サーバーが苦しいときのバックオフ​

エンジンが受け取るすべてのレスポンスは、ストアごとの負荷モニターに送られます。モニターは次の状況に反応します。

  • HTTP 429(即座に反応)
  • 5xxエラーの繰り返し、または通信失敗(1分間に3回)、
  • 継続的な遅さ(応答時間の中央値が2秒超)
  • Retry-After ヘッダー(次回のチェックの下限として厳密に適用されます)

これらの条件のいずれかに該当すると、エンジンは変更チェックの間隔を1段階ずつ2倍に延長し、メンテナンスレーンの実行をすべてスキップします。レジ係が操作するリクエスト — 検索、バーコード検索、チェックアウト — は、速度制限の対象になりません。目的は後回しにできる負荷を減らすことであり、販売を遅らせることではありません。

復旧時の動きは意図的に非対称です。バックオフは即時に行われますが、正常な応答が10回連続するまでは間隔を短縮しません。これにより、不安定なサーバーで高速と低速の間隔が頻繁に切り替わるのを防ぎます。販売者がより高速なプリセットを選んでも、負荷状態は維持されます。この保護機能は設定されたティアの下で動作し、無効にはできません。

デバイス側の応答性を保つ​

パフォーマンスのもう半分はレジ自体です。バックグラウンドの同期がUIをカクつかせてはいけません。

  • 監査処理はイベントループに制御を返します。 整合性監査では作業を分割し、チャンクごとに処理を中断することで、連続実行時間を約30 msに抑えます。これは人が遅延を感じる約100 msのしきい値を下回ります。ローカル商品10,000件で監査全体の計算時間は約68 ms(17回以上の中断に分散)、商品50,000件でも300 ms未満です。
  • 負荷がかかっていても最初の結果は速く表示されます。 一括適用や全件監査が同時に実行されている場合でも、最初の結果が表示されるまでの時間に関する契約は CI で固定されています。ベンチマーク環境では、一般的なカタログサイズで数ミリ秒以内です。
  • 表示中のページだけがアプリに渡されます。 フィルター、並べ替え、ページネーションなどのクエリ処理はストレージ層内で実行されるため、画面の更新で移動するのは1万行ではなく10行です。

これらの数値は、エンジンに固定されたパフォーマンス契約テストスイートから得られたものです。CIで単独実行され、実測された定常状態よりおよそ1桁大きい予算が設定されています。遅い実行環境で失敗させるのではなく、桁違いの性能劣化を検出する設計です。

実際のストアでの検証​

サーバーへの配慮のルールは、ユニットテストだけで確認しているわけではありません。実際のWordPressストアに対するエンドツーエンドのライブチェックにより、実際のホスティングで最も重要な不変条件を検証しています。

  • ストアを開いたとき、商品カタログが描画されるまでのメンテナンスリクエスト(整合性やダイジェストの通信)はゼロであること。
  • 起動後の待機時間が過ぎた後は、低コストの集計ページを数ページ取得し、詳細調査は最大2回までです。

このシナリオは、実際に発生したリグレッションから作られました。開発中の初期ビルドでは、監査がストアを開くたびにデバイスごとに約41件のリクエスト(1.2MB)を発行していました。これを置き換えたダイジェストによるゲート方式の設計では、ずれのない監査は集計ページだけで済み、それ以外は発生しません。この種のバグは現在、レビューの注意深さではなく、CIで宣言された上限によって防がれています。

主張しないこと​

裏付けとなる数値がまだ揃っていないため、このページでは意図的に述べていないことがいくつかあります。

  • 「初回同期はX分かかる」というエンドツーエンドの数値はありません。 初回ダウンロード時間は、主にサーバーの応答時間とカタログの規模によって決まります。デバイス側でレコードを適用するコストは小さく、商品10,000件の一括適用に必要な計算時間は10 ms未満です。大部分を占めるのは通信とサーバーの処理です。
  • 「v1.9よりX%高速」という主張はありません。 アーキテクチャが大きく異なるため、単一の比較数値では有益な情報より誤解を招くおそれがあります。構造上の違いはv1.10.0での変更点で説明しています。
  • 上記のベンチマーク数値はエンジンのテスト環境(メモリ内ストレージ、分離された実行環境)で測定したものです。実際のデバイスや店舗によって異なるため、店舗の健全性 → パフォーマンスでは予測値ではなく、過去24時間のレジで測定されたリクエスト数と典型的な応答時間を表示します。応答サイズが宣言されていない場合はデータ量に加算されないため、データ量の数値は下限値です。

サーバー側のチューニング(ホスティング要件、HPOS、キャッシュ、応答が遅い場合の診断)については、サーバーのパフォーマンスをご覧ください。