Upstash for Redis で Deno アプリのパフォーマンスを向上:応答時間を短縮するサーバーレス キャッシュ
Upstash for Redis とパフォーマンス API に関するこの記事では、Deno アプリで Upstash for Redis を最適に使用する方法を説明します。 Redis 用 Upstash はサーバー側のキャッシュに最適なサーバーレス データベースです。 。私が取り組んでいたウェブ アプリの初期サーバー応答時間のスコアが低かった 。 Lighthouse は 500 ms を報告していました 。 Upstash キャッシュを追加することで、これを150 ミリ秒未満に短縮しました。 そして監査に合格しました。難しいのはキャッシュを追加することではありません。偶然にも、キャッシュをどこで使用するかを検討することが重要でした。パフォーマンスを測定することでのみボトルネックを特定できました。 最小限の作業でパフォーマンスを向上させます。この記事では、パフォーマンスの測定について詳しく説明します。
私のプロジェクトは Deno Fresh Web アプリでした。 Deno は即座にビルドしてデプロイできます。このため、最適化を行うには夢のような環境になります。フィードバック ループは短いです。最適化をローカルでコード化し、サーバーにプッシュすると、即座にリモート サイトをテストできます。
スタック
ここではスケルトンアプリを使ったパフォーマンス向上についてお話します。次のツールを使用します。
upstash_redis:Upstash for Redis を操作するための Deno モジュール- Deno Fresh:Deno でサーバーサイド レンダリング(SSR)アプリを構築するための、本番環境に対応した新しいフレームワーク
- サーバーレス ロギング:ここではコンソールを使用しますが、デプロイされたアプリでライブ測定にアクセスするには、Logtail のようなサービスが必要です
セットアップ
Node と Deno の主な違いは、コード内でサードパーティのモジュールにアクセスする方法です。 Deno は URL を操作し、package.json の代わりにマップをインポートします。 ファイル。 upstash_redis の完全な URL たとえば、https://deno.land/x/upstash_redis@v1.20.0 です。 。まず、新しい Deno Fresh アプリを作成します。
deno run -A -r https://fresh.deno.dev upstash-redis-deno-perf 初めて Deno を試す場合は、いくつかのターミナル コマンドを使用してシステム上に Deno 自体をセットアップできます。
これで、Upstash を import_map.json に追加できるようになりました。 プロジェクトのルート ディレクトリ内:
{
"imports": {
"@/": "./",
"$fresh/": "https://deno.land/x/fresh@1.1.2/",
// ...TRUNCATED
"$std/": "https://deno.land/std@0.177.0/",
"upstash/": "https://deno.land/x/upstash_redis@v1.20.0/"
}
} @/便宜上、インポート別名を定義します。これにより、componentsをインポートできるようになります。 (プロジェクトのルート ディレクトリ内)@/componentsを使用 ソースファイルがどのフォルダにあるかは関係ありません。$std/これは、.envを読み取るためのユーティリティ関数を備えた Deno 標準ライブラリのエイリアスです。 環境変数ファイル。upstash/プロジェクト内の TypeScript または JavaScript ソース ファイルから Upstash for Redis ライブラリにアクセスできるようになります。
Upstash for Redis とパフォーマンス API:スケルトン アプリ
スケルトン アプリは以下を取り込みます:
- Tinybird (サーバーレス クリックハウス) のウェブ分析を使用した過去 28 日間のページビュー
- ページは Webmentions の使用を好みます
これらのデータはフェッチ リクエストを使用して取得されるため、サーバー タスクは現実世界のビジネス アプリをかなり代表するものになります。 likes と views 変数には、フロントエンドに表示するこれら 2 つの API からの応答が保持されます。

サーバー handler そのページのコードは次のようになります:
export const handler: Handlers<Data> = {
async GET(request, context) {
const { url } = request;
const { pathname } = new URL(url);
const likes = await getWebmentionLikes(pathname);
const views = await getTinybirdViews({ days: 28 });
return context.render({ likes, views });
},
};
pathname を抽出します。 受信 request から オブジェクトの場合は、pathname を使用します。 データ ヘルパー関数で使用し、最後にリモートから取得した値を返します。
効率を高めるために、ヘルパー関数の呼び出しを再構成できます。
const [likes, views] = await Promise.all([
getWebmentionLikes(pathname),
getTinybirdViews({ days: 28 }),
]); JavaScript パフォーマンス Web API
通常、パフォーマンスの測定は最適化の最初のステップとなります。レート制限ステップは、必ずしも期待どおりであるとは限りません。測定を行わないと、結果的に最適ではないソリューションに時間とリソースを費やすことになりがちです。 Performance API はここでも役に立ちます。このセクションでは、アプリ内で Upstash for Redis を使用するのが最も合理的な場所を判断するためにこれを使用する方法を説明します。
window.performance クライアント ブラウザからパフォーマンス Web API にアクセスできるようになります。 Deno はサーバー上での Web API の使用をサポートしているため、performance Deno サーバー側コードでグローバルに利用可能です。以下に、使用したい 2 つのパフォーマンス方法を示します。
performance.mark('your-mark-name'):PerformanceMarkを作成します ある時点を表すオブジェクト。 name パラメータは、マークを含むメジャーを作成するときに使用されます。performance.measure('your description', startMarkName, finishMarkName):PerformanceMeasureを作成します オブジェクト。これにより、開始時刻と終了時刻のマークがラベルに関連付けられ、イベントの実行にかかった時間を記録したり計算したりするのに役立ちます。
timeEvent :パフォーマンスヘルパー関数
基本がわかったので、timeEvent を作成しましょう。 機能。 PerformanceMeasure の配列を受け取ります。 入力として時間を測定したいオブジェクトと関数。 timeEvent 開始マークを作成し、渡された関数を呼び出し、すぐに終了マークを作成します。最後に、PerformanceMeasure の配列を変更します。 入力として受け取ったオブジェクトを追加し、新しいオブジェクトを追加します。 utils/performance.ts のコードは次のとおりです。 :
export async function timeEvent<EventReturnType>(
eventFunction: () => Promise<EventReturnType>,
{
description,
performanceMeasures,
}: { description: string; performanceMeasures: PerformanceMeasure[] },
): Promise<EventReturnType> {
// prepare
const startName = `${description}-started`;
const finishName = `${description}-finished`;
// time
performance.mark(startName);
const result = await eventFunction();
performance.mark(finishName);
// record
performanceMeasures.push(
performance.measure(description, startName, finishName),
);
return result;
}
この関数は汎用ですが、スケルトン アプリの場合は EventReturnType です。 常に数値になります。
測定によるサーバー コードの更新
新しい timeEvent を使用できます。 ハンドラー内の関数を使用して、比較の実行を開始します。更新されたサーバー ハンドラー コードは次のとおりです。
import type { Handlers, PageProps } from "$fresh/server.ts";
import "$std/dotenv/load.ts"; /* included for visibility here, typically you
can import once for project in `dev.ts` */
import { timeEvent } from "@/utils/performance.ts";
// ...TRUNCATED
export const handler: Handlers<Data> = {
async GET(request, context) {
// ...TRUNCATED
const performanceMeasures: PerformanceMeasure[] = [];
const [likes, views] = await Promise.all([
timeEvent<number>(() => getWebmentionLikes(pathname), {
description: "web-mention-likes",
performanceMeasures,
}),
timeEvent<number>(() => getTinybirdViews({ days: 28 }), {
description: "analytics-views",
performanceMeasures,
}),
]);
// Replace with a serverless logging service for production
console.log({ performanceMeasures });
return context.render({ likes, views });
},
};
timeEvent function は、渡した関数の結果を返します。このプロパティを使用すると、以前に timeEvent にあった 2 つのデータ ヘルパー関数をラップするだけで済みます。 呼び出します。ここではローカルで実行しています。実稼働アプリの場合、サーバー上のバックボーン接続はローカル接続とは異なる動作をするため、ライブサイトで測定を実行する必要があります。サーバー上で実行する場合は、Logtail などのログ サービスを使用して測定値を記録します。

コンソール ログのキャプチャでは、PerformanceMeasure が確認できます。 オブジェクトは、次のメジャー値 (前述した) を提供します。
- 名前
- 開始時間
- 期間 (ミリ秒単位)
理想的には、アプリをレンダリングするには両方のデータ値 (likes と views ) が必要です。ここでは、お互いにほぼ同じ時間(2 秒)かかりました。 1 つの関数の実行速度が他の関数よりもはるかに遅い場合は、最も遅い値を得るために Upstash for Redis キャッシュを追加します。代わりに、ここでは両方に追加します。運用環境では、少なくとも数百のデータ ポイントが必要になることに注意してください。その後、平均や P90 などの集計指標を比較に使用できます。
分析ヘルパー コードへの Upstash for Redis の追加
Upstash for Redis を分析ヘルパー関数に追加するコードを見てみましょう。 Webmentions ヘルパー関数も同様で、GitHub リポジトリ (以下のリンク) で完全に参照できます。
import { Redis } from "upstash/mod.ts";
const UPSTASH_REDIS_REST_TOKEN = Deno.env.get("UPSTASH_REDIS_REST_TOKEN");
if (typeof UPSTASH_REDIS_REST_TOKEN === "undefined") {
console.error("env `UPSTASH_REDIS_REST_TOKEN` must be set");
}
const UPSTASH_REDIS_REST_URL = Deno.env.get("UPSTASH_REDIS_REST_URL");
if (typeof UPSTASH_REDIS_REST_URL === "undefined") {
console.error("env `UPSTASH_REDIS_REST_URL` must be set");
}
const redis = new Redis({
token: UPSTASH_REDIS_REST_TOKEN,
url: UPSTASH_REDIS_REST_URL,
});
まず、Upstash for Redis オブジェクトを初期化する必要があります。 UPSTASH_REDIS_REST_TOKEN が必要です および UPSTASH_REDIS_REST_URL Upstash コンソールからの値。 Upstash アカウントをまだお持ちでない場合は、すぐにセットアップできます。両方の値を追加します (UPSTASH_REDIS_REST_TOKEN) と UPSTASH_REDIS_REST_URL ) から .env プロジェクトのルート ディレクトリにあるファイル。
上の最初の行では、upstash を使用していることに注意してください。 先ほど設定したインポートマップのキー。これは、各 TypeScript ファイルに完全なインポート URL を追加するよりも便利です。 upstash_redis の次のリリース時 利用可能になると、バージョン番号を 1 か所で更新するだけで済みます。
getTinybirdViews は次のとおりです。 関数:
export async function getTinybirdViews({
days,
}: {
days: number;
}): Promise<number> {
try {
// ...TRUNCATED
const cachedCount = (await redis.get("view-count")) as number | null;
if (cachedCount != null) {
return cachedCount;
}
// ...TRUNCATED
const response = await fetch(
`https://api.tinybird.co/v0/pipes/${TINYBIRD_PIPE_NAME}.json?${params.toString()}`,
{
headers: {
Authorization: `Bearer ${TINYBIRD_TOKEN}`,
},
},
);
const {
data: [{ count_sessions: count = -1 }],
} = await response.json();
if (typeof count === "number" && count > 0) {
const CACHE_TTL_SECONDS = 14_400;
await redis.set("view-count", count);
await redis.expire("view-count", CACHE_TTL_SECONDS);
}
return count;
} catch (error: unknown) {
// ...TRUNCATED
}
} ここでは次のようにします。
<オル>view-count の Upstash for Redis のキャッシュ値がすでに存在するかどうかを確認します redis.get('view-count') への呼び出しによる .redis.set('view-count', value) を呼び出して、Upstash for Redis キャッシュに新しい値を保存し、有効期限を設定します 次に redis.expire(TTL) 。これにより、 値に生存時間が設定されます。 (TTL ) この値を超えると、データは古いとみなされます。 TTL を設定します ここで4時間まで。 getTinybirdViews への通話の場合 その期間が経過すると、Tinybird にアクセスして新しい値を取得します。

両方のデータ クエリに Upstash for Redis を統合してページを (数回) 更新すると、速度が向上することがわかります。ここでは、2 秒強から約 0.29 秒まで短縮されました。ローカルで実行しており、データ ポイントもそれほど多くないため、ここでの数値をあまり深く読み込まないでください。独自のアプリでこのサービスを試して、どのようなメリットが得られるかを確認してください。
Upstash for Redis とパフォーマンス API:まとめ
ここでは、JavaScript Performance API を使用して、どこに最適化の取り組みを集中するかを決定するのに役立つ方法を説明しました。さらに、Deno Fresh で Upstash for Redis を実装する方法を確認しました。最後に、Deno が Web API サーバー側をサポートしていることを発見し、学習曲線を平坦化しました。最適化における Deno のもう 1 つの大きなメリットは、即時デプロイにより短いフィードバック ループが得られ、パフォーマンスを微調整する際に迅速に対応できることです。
Upstash for Redis と Performance API について読んで価値があると感じていただければ幸いです。 Deno または Deno Fresh を初めて使用する場合は、Deno の使用開始に関して私が作成したコンテンツの一部をご覧ください。アプリの完全なコードは GitHub で開くことができます。
-
HashiCorpTerraformを使用してRedisEnterpriseCloudAnywhereをプロビジョニングおよび管理する
本日、HashiCorp Terraform RedisEnterpriseCloudプロバイダーが利用可能になったことをお知らせします。開発チームは継続的インテグレーション/継続的デリバリー(CI / DC)などのDevOpsの原則をますます採用していますが、コードとしてインフラストラクチャを管理する必要性は、クラウドサービスにとってほぼ必須の機能になっています。コードスペースとしてのインフラストラクチャの主要なツールはHashiCorpTerraformであり、クラウド、インフラストラクチャ、およびサービスのプロビジョニング、コンプライアンス、および管理のためのプロバイダーとモジュールのク
-
Redis マルチリージョン アーキテクチャの習得:レイテンシ、レプリケーション、現実世界の課題
このビデオを表示するには、JavaScript を有効にし、HTML5 ビデオをサポートする Web ブラウザへのアップグレードを検討してください。 3月18日 508 500 1 Cシャープテレビ 全ライブC#コーナーの公式アカウントです。 おすすめの動画 Redis 分散ロックの説明:安全なパターンと一般的な落とし穴 バイバフ・クマール 3月16日 2.9k 500 Redis とインメモリ キャッシュ:開発者が犯すスケーリングの間違い バイバフ・クマール 3月11日 2.5k 500 Redis Sentin