Ich habe gefragt, was nun eine von der Community gelöschte Frage zu SO ist, warum jemand Javascript verwenden sollte Promise.race
, und ein hochrangiger Benutzer hat dies kommentiert:
Wenn Sie zwei Dienste haben, die einen Wert berechnen, können Sie beide parallel abfragen und den jeweils zuerst zurückgegebenen Wert verwenden, anstatt einen abzufragen, auf einen Fehler zu warten und dann den zweiten abzufragen.
Ich habe über Redundanz und diesen Anwendungsfall im Allgemeinen gegoogelt, aber ich konnte nichts finden, und aus meiner Sicht ist es nie eine gute Idee, einem Server / Dienst einfach eine Arbeitslast hinzuzufügen, wenn Sie die Antwort nicht verwenden.
programming-practices
Adelin
quelle
quelle
Antworten:
Ich würde argumentieren, dass dies eher eine ökonomische Frage ist. Dies ist jedoch ein Urteil, zu dem Ingenieure fähig sein sollten. Daher antworte ich.
Ich teile meine Antwort in vier Teile:
Risikomanagement
Daher kann es vorkommen, dass Ihr Client keine Antwort vom Server erhält. Ich gehe davon aus, dass dies nicht auf einen Programmfehler zurückzuführen ist (ansonsten besteht die Lösung darin, ihn zu beheben, also mach das). Stattdessen muss es sich um eine zufällige Situation handeln, auf die Sie keinen Einfluss haben ...
Aber nicht jenseits Ihres Wissens. Du musst wissen:
Wenn beispielsweise ein Fehler auftritt und nur in etwa 2% der Fälle ein erneuter Versuch unternommen wird, lohnt es sich wahrscheinlich nicht, ihn zu beheben. Wenn es ungefähr 80% der Zeit passiert, hängt es davon ab,
Wie viel Zeit muss der Kunde warten? Und wie sich das in Kosten niederschlägt ... Sie haben eine kleine Verzögerung bei einer regulären Bewerbung, es ist wahrscheinlich keine große Sache. Wenn es wichtig ist und Sie über eine Echtzeitanwendung oder ein Online-Videospiel verfügen, werden Benutzer abgelehnt, und Sie sollten wahrscheinlich besser in mehr oder bessere Server investieren. Andernfalls können Sie wahrscheinlich eine Meldung "Laden" oder "Warten auf Server" einfügen. Wenn die Verzögerung nicht wirklich groß ist (in der Größenordnung von zehn Sekunden), kann sie selbst für die reguläre Anwendung zu groß sein.
Strategien
Wie ich oben sagte, gibt es mehr als einen Weg, um dieses Problem zu lösen. Ich gehe davon aus, dass Sie bereits die Try-Fail-Retry-Schleife implementiert haben. Also, mal sehen ...
Jetzt merke ich, dass diese immer noch scheitern können. Wenn wir davon ausgehen, dass eine Abfrage an einen Server eine Ausfallwahrscheinlichkeit von 80% hat, hat eine parallele Abfrage an zwei Server eine Ausfallwahrscheinlichkeit von 64%. Daher müssen Sie es möglicherweise noch einmal versuchen.
Ein zusätzlicher Vorteil der Auswahl des schnelleren Servers und seiner weiteren Verwendung besteht darin, dass die Wahrscheinlichkeit eines Ausfalls des schnelleren Servers aufgrund von Netzwerkproblemen geringer ist.
Was mich daran erinnert, wenn Sie herausfinden können, warum die Anfrage fehlschlägt, tun Sie dies. Es kann Ihnen helfen, die Situation besser zu meistern, auch wenn Sie die Ausfälle nicht verhindern können. Benötigen Sie beispielsweise mehr Übertragungsgeschwindigkeit auf der Serverseite?
Etwas mehr:
Und wer hat gesagt, dass Sie nur eines davon tun müssen? Sie können eine Lademeldung einfügen, mehrere Server abfragen, die über den gesamten Wrold verteilt sind, um die schnelleren zu ermitteln, und von da an bei einem erneuten Fehlversuch in einer Schleife nur diese Server verwenden. Jeder dieser Server kann ein Cluster von Computern mit Lastenausgleich sein . Warum nicht? Na ja, kostet ...
Kosten
Es gibt vier Kosten:
Sie müssen sie ausbalancieren.
Nehmen wir zum Beispiel an, Sie verdienen ungefähr einen Dollar pro zufriedenen Benutzer. Das haben Sie 3000 Benutzer pro Tag. Dass die Anfragen in etwa 50% der Fälle fehlschlagen. Und dass 2% der Nutzer ohne Bezahlung abreisen, wenn die Anfrage fehlschlägt. Dies bedeutet, dass Sie 30 Dollar pro Tag verlieren (3000 * 50% * 2%). Angenommen, die Entwicklung der neuen Funktion kostet 100 US-Dollar, und die Bereitstellung der Server kostet 800 US-Dollar. Wenn Sie die Laufzeitkosten außer Acht lassen, bedeutet dies, dass sich die Investition in ((100 + 800) / 30 rentiert ) 30 Tage. Jetzt können Sie Ihr Budget überprüfen und entscheiden.
Betrachten Sie diese Werte nicht als repräsentativ für die Realität, ich habe sie aus mathematischen Gründen ausgewählt.
Nachträge:
Die Sache ist, dass Sie, wenn Sie das Problem in Bezug auf die Ausgleichskosten betrachten, eine Schätzung der Kosten für die Strategien vornehmen können, die Sie in Betracht ziehen, und diese Analyse verwenden, um zu entscheiden.
Intuition
Intuition wird durch Erfahrung gefördert. Ich schlage nicht vor, diese Art von Analyse jedes Mal durchzuführen. Einige Leute tun es, und das ist in Ordnung. Ich schlage vor, dass Sie dies verstehen und eine Intuition dafür entwickeln.
Darüber hinaus lernen wir im Ingenieurwesen neben dem Wissen, das wir aus der tatsächlichen Wissenschaft erhalten, auch in der Praxis und erstellen Richtlinien darüber, was funktioniert und was nicht. Daher ist es oft ratsam zu sehen, wie der Stand der Technik ist ... obwohl Sie manchmal außerhalb Ihrer Region sehen müssen.
In diesem Fall würde ich mir Online-Videospiele ansehen. Sie haben Ladebildschirme, sie haben mehrere Server, sie wählen einen Server basierend auf der Latenz und sie können dem Benutzer sogar erlauben, Server zu wechseln. Wir wissen, dass das funktioniert.
Ich würde vorschlagen, dies zu tun, anstatt bei jeder Anforderung Netzwerkverkehr und Serverzeit zu verschwenden. Beachten Sie auch, dass selbst bei redundanten Servern Fehler auftreten können.
quelle
Dies ist akzeptabel, wenn die Zeit des Clients wertvoller ist als die Zeit auf dem Server.
Wenn der Kunde schnell und genau sein muss. Sie können die Abfrage mehrerer Server rechtfertigen. Und es ist schön, die Anfrage abzubrechen, wenn eine gültige Antwort eingeht.
Und natürlich ist es immer ratsam, die Eigentümer / Manager der Server zu konsultieren.
quelle
Diese Technik kann die Latenz reduzieren. Die Antwortzeit des Servers ist nicht deterministisch. In der Größenordnung ist es wahrscheinlich, dass mindestens ein Server schlechte Antwortzeiten aufweist. Jeder, der diesen Server verwendet, hat daher auch schlechte Antwortzeiten. Durch das Senden an mehrere Server wird das Risiko verringert, mit einem Server mit schlechter Leistung zu kommunizieren.
Die Kosten umfassen zusätzlichen Netzwerkverkehr, verschwendete Serververarbeitung und Anwendungskomplexität (obwohl dies in einer Bibliothek verborgen sein kann). Diese Kosten können reduziert werden, indem nicht verwendete Anforderungen storniert werden oder kurz gewartet wird, bevor eine zweite Anforderung gesendet wird.
Hier ist ein Papier , und ein anderer . Ich erinnere mich, dass ich in einem Google-Artikel auch deren Implementierung gelesen habe.
quelle
Ich stimme den anderen Antworten größtenteils zu, denke aber, dass dies in der Praxis äußerst selten sein sollte. Ich wollte ein viel häufigeres und vernünftigeres Beispiel dafür geben, wann Sie es verwenden würden
Promise.race()
, etwas, das ich vor ein paar Wochen zufällig verwendet habe (nun, Pythons Äquivalent).Angenommen, Sie haben eine lange Liste von Aufgaben, von denen einige parallel ausgeführt werden können und einige vor anderen ausgeführt werden müssen. Sie können alle Aufgaben ohne Abhängigkeiten starten und dann mit auf diese Liste warten
Promise.race()
. Sobald die erste Aufgabe abgeschlossen ist, können Sie alle Aufgaben starten, die von dieser ersten Aufgabe undPromise.race()
erneut von der neuen Liste in Kombination mit den noch nicht abgeschlossenen Aufgaben aus der ursprünglichen Liste abhängen . Wiederholen Sie dies, bis alle Aufgaben erledigt sind.Hinweis: Die API von Javascript ist dafür nicht ideal geeignet. Es ist so ziemlich das Nötigste, was funktioniert, und Sie müssen einiges an Klebercode hinzufügen. Mein Punkt ist jedoch, dass Funktionen wie
race()
selten für Redundanz verwendet werden. Sie sind in erster Linie dazu da, wenn Sie die Ergebnisse aus allen Versprechungen erhalten möchten, aber nicht darauf warten möchten, dass sie alle abgeschlossen sind, bevor Sie weitere Maßnahmen ergreifen.quelle
new Promise
aufgerufen werden, und nicht neu gestartet, wenn siePromise.race()
aufgerufen werden. Einige Implementierungen von Versprechungen sind faul, aber Eifer ist weitaus häufiger. Sie können dies testen, indem Sie in der Konsole ein Versprechen erstellen, das sich bei der Konsole anmeldet. Sie werden sehen, dass es sofort protokolliert wird. Dann geben Sie dieses Versprechen anPromise.race()
. Sie werden sehen, es wird nicht erneut protokolliert.Zusätzlich zu den technischen Überlegungen können Sie diesen Ansatz verwenden, wenn er Teil Ihres tatsächlichen Geschäftsmodells ist.
Variationen dieses Ansatzes sind bei Echtzeitgeboten für Anzeigen relativ häufig . In diesem Modell fordert ein Publisher (Werbeflächenanbieter) Werbetreibende (Werbeanbieter) auf, auf eine Impression eines bestimmten Nutzers zu bieten . So wird für jeden solchen Eindruck, würden Sie jede der Werbetreibende abfragen abonniert hat , zu einem Endpunkt eine Abfrage mit dem Eindruck Details Senden von jedem Werbetreibenden zur Verfügung gestellt (oder alternativ ein Skript durch die Werbenden bereitgestellt als ein Endpunkt auf Ihrem eigenen Server ausgeführt wird ), Rennen alle diese Anfragen bis zu einem Timeout (zB 100ms) und dann das höchste Gebot nehmen, die anderen ignorieren.
Eine besondere Variante, die die Wartezeit des Kunden verkürzt, besteht darin, dass der Publisher einen Mindestzielwert für das Gebot zulässt, sodass das erste Gebot des Werbetreibenden, das diesen Wert übersteigt, sofort akzeptiert wird (oder falls keines der Gebote übersteigt) der Wert, der maximale wird genommen). In dieser Variante könnte also die erste ankommende Abfrage gewinnen und die andere verworfen werden, selbst wenn sie genauso gut oder sogar noch besser sind.
quelle