Heim  >  Artikel  >  Web-Frontend  >  Beispiel für eine Strombegrenzungsmethode für Koa-Dienste

Beispiel für eine Strombegrenzungsmethode für Koa-Dienste

小云云
小云云Original
2018-05-15 10:47:532004Durchsuche

Die Anforderung der Strombegrenzung besteht darin, die Anzahl gleichzeitiger Ausführungen zu begrenzen. Nachdem diese Anzahl überschritten wurde, muss sie in einer Warteschlange zwischengespeichert werden. In diesem Artikel wird hauptsächlich die Praxis der Koa-Servicestrombegrenzungsmethode vorgestellt. Der Herausgeber findet sie recht gut. Jetzt werde ich sie mit Ihnen teilen und Ihnen eine Referenz geben. Folgen wir dem Herausgeber und schauen wir uns das an. Ich hoffe, es kann allen helfen.

Ich habe kürzlich eine Anfrage erhalten. Es ist ganz einfach: Richten Sie einfach einen Server ein, rufen Sie beim Empfang der Anfrage eine bereitgestellte Schnittstelle auf und geben Sie dann das Ergebnis zurück. Aufgrund der Leistungsprobleme dieser Schnittstelle darf die Anzahl der gleichzeitigen Anforderungen eine bestimmte Anzahl nicht überschreiten und der Strom muss im Dienst begrenzt werden.

Koa-Middleware ruft die nächste Funktion nicht auf

Die ursprüngliche Idee besteht darin, Koa-Middleware einzubeziehen und die nächste Funktion zwischenzuspeichern, wenn mehr als 6 vorhanden sind. Wenn die laufende Aufgabe beendet ist, rufen Sie next auf, um andere Anforderungen fortzusetzen.

Später habe ich festgestellt, dass die nächste Funktionsanforderung in der Koa-Middleware nicht gestoppt wird. Stattdessen wird die nachfolgende Middleware nicht mehr aufgerufen und der Inhalt wird direkt zurückgegeben.

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);

Der obige Code gibt zuerst „Middleware 1“ auf der Konsole aus => Der Browser empfängt „Hallo“ => Die Konsole gibt „Middleware 2“ aus.

Eine weitere Sache, die hier zu beachten ist, ist, dass nach dem Ende einer Anfrage (Finish) die nächste Methode immer noch aufgerufen werden kann und die nachfolgende Middleware weiterhin ausgeführt wird (die Änderung an ctx wird jedoch nicht wirksam, da die Anfrage wurde zurückgegeben). Ebenso verhält sich die Schließanforderung (close).

Warten zu verwenden, um die Anfrage warten zu lassen

Eine Verzögerung der Ausführung der nächsten Funktion kann den Zweck nicht erreichen. Der nächste logische Schritt besteht darin, mit „await“ auf die aktuelle Anfrage zu warten. Die Wait-Funktion gibt ein Promise zurück. Wir speichern die Resolve-Funktion in diesem Promise in der Warteschlange und verzögern den Aufruf.

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);

Der obige Code gibt ein Versprechen in der Verzögerungsfunktion zurück und die Auflösungsfunktion des Versprechens wird in der Warteschlange gespeichert. Stellen Sie den Timer so ein, dass die Auflösungsfunktion in der Warteschlange nach 3 Sekunden ausgeführt wird, damit die Anfrage weiterhin ausgeführt werden kann.

Ist der Fluss für Routen oder für Anfragen begrenzt?

Nachdem das Grundprinzip der Strombegrenzung implementiert ist, stellt sich als nächstes die Frage: Wo soll der Strombegrenzungscode geschrieben werden? Grundsätzlich gibt es zwei Standorte:

Strombegrenzung für Schnittstellen

Aufgrund unserer Bedürfnisse ist die Strombegrenzung auf die begrenzte Leistung der angeforderten Schnittstelle zurückzuführen. Daher können wir den Fluss dieser Anfrage separat einschränken:

async function requestSomeApi() {
 // 如果已经超过了最大并发
 if (counter > maxAllowedRequest) {
  await delay();
 }
 counter++;
 const result = await request('http://some.api');
 counter--;
 queue.shift()();
 return result;
}

Es gibt unten auch eine praktische wiederverwendbare Version.

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;
 }
}

Begrenzen Sie den Fluss für das Routing

Diese Methode besteht darin, eine Koa-Middleware zu schreiben und den Fluss in der Middleware zu begrenzen:

async function limiter(ctx, next) => {
 // 如果超过了最大并发数目
 if (counter >= maxAllowedRequest) {
  // 如果当前队列中已经过长
  await new Promise((resolve, reject) => {
   queue.push(resolve);
  });
 }
 store.counter++;
 await next();
 store.counter--;
 queue.shift()();
};

Dann verwenden Sie einfach diese Middleware im Router für verschiedene Routen:

router.use('/api', rateLimiter);

Vergleiche

, um eine Strombegrenzung für die Schnittstelle zu implementieren, was logisch erscheint. Es war ein bisschen chaotisch, also habe ich auf Routing-spezifische Verkehrsbegrenzung umgestellt und alles lief perfekt.

Bis ich eine weitere Anfrage erhielt, wollte ich diese Schnittstelle dreimal anfordern und das Ergebnisarray der drei Anfragen zurückgeben. Jetzt kommt das Problem, wir können die Schnittstelle nicht direkt aufrufen, da der Strom begrenzt ist. Sie können die Funktion der Anforderungsschnittstelle nicht direkt aufrufen, da unser aktuelles Limit auf dem Routing basiert. Was zu tun? Wir können diese Route nur anfordern und selbst anfordern. . .

Wichtige Dinge

Abhören des Schließereignisses und Entfernen der Anfrage aus der Warteschlange
Anfragen, die in der Warteschlange gespeichert wurden, können vom Benutzer abgebrochen werden Zustand. Wie bereits erwähnt, wird die nachfolgende Middleware auch dann ausgeführt, wenn die Anforderung in KOA abgebrochen wird. Dies bedeutet, dass auch Schnittstellen ausgeführt werden, die eine Strombegrenzung erfordern, was zu Verschwendung führt.

Sie können sich das Abschlussereignis anhören, um diesen Zweck zu erreichen. Wir müssen jede Anfrage mit einem Hash-Wert markieren:

ctx.res.on('close', () => {
 const index = queue.findIndex(item => item.hash === hash);
 if (index > -1) {
  queue.splice(index, 1);
 }
});

Legen Sie das Timeout fest

Um zu verhindern, dass Benutzer zu lange warten, müssen Sie ein Timeout festlegen, das in koa einfach zu implementieren ist:

const server = app.listen(config.port);
server.timeout = DEFAULT_TIMEOUT;

Die aktuelle Warteschlange ist bereits zu lang

Wenn die aktuelle Warteschlange bereits zu lang ist, kommt es auch beim Beitritt zur Warteschlange zu einer Zeitüberschreitung. Daher müssen wir uns auch mit der Situation befassen, in der die Warteschlange zu lang ist:

if (queue.length > maxAllowedRequest) {
 ctx.body = 'error message';
 return;
}

Verwandte Empfehlungen:

Der Weg des Java-Architekten – Strombegrenzungstechnologie und verschiedene Programmiersprachen

Nginx-Strombegrenzungsalgorithmus

Verwenden Sie Redis zur Strombegrenzung

Das obige ist der detaillierte Inhalt vonBeispiel für eine Strombegrenzungsmethode für Koa-Dienste. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn