ホームページ > 記事 > ウェブフロントエンド > Koaサービスの電流制限方法例
電流制限の要件は、同時実行数を制限することです。この数を超えた後は、キューにキャッシュする必要があります。この記事では主に Koa サービスの電流制限方法の実践方法を紹介します。これが非常に優れていると思いますので、参考にしてください。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。
最近リクエストを受け取りました。サーバーをセットアップし、リクエストを受信したときに提供されたインターフェイスを呼び出し、結果を返すだけです。このインターフェイスのパフォーマンスの問題のため、同時にリクエストの数は一定の数を超えることができず、サービス内の電流を制限する必要があります。
koa ミドルウェアは next を呼び出しません
本来のアイデアは、koa ミドルウェアでカウントし、6 つ以上の関数がある場合に次の関数をキャッシュすることです。進行中のタスクが終了したら、next を呼び出して他のリクエストを続行します。
その後、koa ミドルウェアでは、次の関数リクエストが実行されないと停止せず、後続のミドルウェアが呼び出されなくなり、コンテンツが直接返されることがわかりました。
const Koa = require('koa'); const app = new Koa(); app.use((ctx, next) => { console.log('middleware 1'); setTimeout(() => { next(); }, 3000); ctx.body = 'hello'; }); app.use((ctx, next) => { console.log('middleware 2'); }); app.listen(8989);
上記のコードは、まずコンソールに「ミドルウェア 1」を出力します => ブラウザは「hello」を受信します => コンソールは「ミドルウェア 2」を出力します。
ここでもう 1 つ注意すべき点は、リクエストが終了 (終了) した後も、その次のメソッドを呼び出すことができ、後続のミドルウェアは引き続き実行されるということです (ただし、リクエストが返されているため、ctx への変更は有効になりません) )。同様に、クローズ要求 (close) も同様に動作します。
awaitを使ってリクエストを待たせる
次の関数の実行を遅らせても目的は達成できません。次に考えられるのは、現在のリクエストを待つために await を使用することです。 await 関数は Promise を返します。この Promise 内のsolve 関数をキューに格納し、呼び出しを遅延させます。
const Koa = require('koa'); const app = new Koa(); const queue = []; app.use(async (ctx, next) => { setTimeout(() => { queue.shift()(); }, 3000); await delay(); ctx.body = 'hello'; }); function delay() { return new Promise((resolve, reject) => { queue.push(resolve); }); } app.listen(8989);
上記のコードは、Delay関数でPromiseを返し、そのPromiseのresolve関数がキューに格納されます。リクエストの実行を継続できるように、キュー内の解決関数を 3 秒後に実行するようにタイマーを設定します。
フローはルーティングまたはリクエストに対して制限されていますか?
電流制限の基本原理が実装された後、次の問題は、電流制限コードをどこに記述すべきかということです。基本的に、次の 2 つの立場があります:
インターフェースの電流制限
ニーズにより、電流制限は、要求されたインターフェースの制限されたパフォーマンスによるものです。したがって、このリクエストのフローを個別に制限できます:
async function requestSomeApi() { // 如果已经超过了最大并发 if (counter > maxAllowedRequest) { await delay(); } counter++; const result = await request('http://some.api'); counter--; queue.shift()(); return result; }
以下に便利な再利用可能なバージョンもあります。
async function limitWrapper(func, maxAllowedRequest) { const queue = []; const counter = 0; return async function () { if (counter > maxAllowedRequest) { await new Promise((resolve, reject) => { queue.push(resolve); }); } counter++; const result = await func(); counter--; queue.shift()(); return result; } }
ルートの電流制限
この方法は、koa ミドルウェアを作成し、ミドルウェアの電流を制限することです:
async function limiter(ctx, next) => { // 如果超过了最大并发数目 if (counter >= maxAllowedRequest) { // 如果当前队列中已经过长 await new Promise((resolve, reject) => { queue.push(resolve); }); } store.counter++; await next(); store.counter--; queue.shift()(); };
その後、ルーターでこのミドルウェアをさまざまなルートに使用するだけです:
router.use('/api', rateLimiter);
比較
インターフェイスに電流制限を実装しましたが、ロジックが少し複雑だと思ったので、ルーティングの電流制限に切り替えました。すべてが完璧に動作しました。
別のリクエストを受け取るまで、このインターフェイスを 3 回リクエストし、3 つのリクエストの結果配列を返したいと考えていました。ここで問題が発生します。電流が制限されているため、インターフェイスを直接呼び出すことができません。現在の制限はルーティングに基づいているため、リクエスト インターフェイスの関数を直接呼び出すことはできません。それではどうすればいいでしょうか?このルートは自分たちでリクエストしてリクエストするしかありません。 。 。
注意事項
closeイベントをリッスンして、キューからリクエストを削除してください
キューに格納されたリクエストは、ユーザーによってキャンセルされる可能性があります。前述したように、koa でリクエストがキャンセルされても、後続のミドルウェアは実行され続けるため、電流制限が必要なインターフェイスも実行されてしまい、無駄が発生します。
この目的を達成するには、各リクエストをハッシュ値でマークする必要があります:
ctx.res.on('close', () => { const index = queue.findIndex(item => item.hash === hash); if (index > -1) { queue.splice(index, 1); } });
タイムアウトを設定します
ユーザーが長時間待機しないようにするには、 koa では簡単な timeout 実装:
const server = app.listen(config.port); server.timeout = DEFAULT_TIMEOUT;
現在のキューが長すぎます
現在のキューが長すぎる場合は、キューに参加してもタイムアウトになります。したがって、キューが長すぎる状況にも対処する必要があります:
if (queue.length > maxAllowedRequest) { ctx.body = 'error message'; return; }
関連する推奨事項:
Java アーキテクトの道 - 電流制限技術とさまざまなプログラミング言語
以上がKoaサービスの電流制限方法例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。