背景
・それほどアクティブユーザーがいないウェブアプリケーションにおいて、やたらDB負荷が高かったりした際に、色々調査して、負荷対策や効率化を行なった際の話
静的なコンテンツに関しては、リクエスト時のxhrオブジェクトを再利用する
静的コンテンツの取得に関しては、同じリクエストパラメータで複数回リクエストを送信する設計を避け、既に実行された xhr オブジェクトの再利用を行うことで、サーバー負荷の軽減を図ります。
// サンプルコード
var requestCache = {};
function fetchContent(params) {
var key = JSON.stringify(params);
if (requestCache[key]) {
return requestCache[key]; // 既存のxhrオブジェクトをそのまま返却
} else {
var xhr = $.ajax({
type: "GET",
url: "your-endpoint",
data: params
});
requestCache[key] = xhr; // xhrオブジェクトをキャッシュに保存
return xhr;
}
}
このコードでは、リクエストパラメータをキーとして xhr オブジェクトをキャッシュし、次回のリクエスト時に既存のキーが存在する場合は、保存された xhr オブジェクトをそのまま返却します。これにより、同じリクエストに対しては、新たなネットワークリクエストを行わずに済みます。
このようなキャッシュ戦略を採用することで、静的なコンテンツの効率的な取得と、サーバーへの無駄なリクエストの削減が実現されます。
この利点は、たとえば開発者ツールなどでリクエストが保留中のものがあった時、無駄に追加でネットワーク接続をつくらず、保留中のオブジェクトの結果を待ちます。
このオブジェクトの結果についてサーバー側でエラーだったりして保留中のままだったりするケースがあるので、timeoutさせたり、エラーハンドリングは必須です。
2. 動的なコンテンツに関しては、更新頻度を考慮して取得結果のキャッシュを制御する
動的コンテンツの場合、更新頻度を考慮して、キャッシュの有効期間やリフレッシュ戦略を適切に設計することが重要です。
1分未満で更新されるコンテンツであればそもそも都度リクエストさせる場合が好ましいでしょう
ただ1ユーザーが同じようなリクエストを何度も行う可能性があるユースケースがあるのであれば、負荷軽減でもう少し取得間隔を設ける(30秒に1回ぐらい同じ結果にする?)とか
// サンプルコード
function fetchDynamicContent(params) {
var key = JSON.stringify(params);
var cache = requestCache[key];
if (cache && cache.timestamp > Date.now() - 300000) { // 5分間のキャッシュ
return Promise.resolve(cache.data);
} else {
return $.ajax({
type: "GET",
url: "your-endpoint",
data: params
}).done(function(response) {
requestCache[key] = { data: response, timestamp: Date.now() };
return response;
});
}
}
あとがき
コードに関しては、AIにかかせたので動作確認はしてください。
上記は私も直近ajax通信周りで負荷軽減対策を行なって、比較的ベストプラクティスに近いのかな〜〜と思ったのでまとめました。
(その道のプロからしたら初歩中の初歩みたいな話かも...
ていうかajaxの中にcache: true みたいなオプションがあるんだけど、同じパラメータリクエストを送っても上記のように保留中のxhrオブジェクトを再利用してくれたり...なんてことはなかった(してくれるものだと思ってた(もしかして私の書き方がよくなかった?本当はしてくれる?詳しい人教えて