Eine nicht blockierende Anforderung mit Anforderungen, wenn die Laufenden Kolben mit Gunicorn und Gevent
Meine Flask-Anwendung wird eine Anfrage erhalten, einige Berechnungen durchführen, und dann eine Anfrage zu einem langsamen externen Endgeräte-Endpunkt-das dauert 5 Sekunden, um zu reagieren. Wie es aussieht, läuft Gunicorn mit Gevent wird es ermöglichen, behandeln viele dieser langsame-Anfragen zur gleichen Zeit. Wie kann ich ändern Sie das Beispiel unten, so dass die Sicht nicht blockiert?
import requests
@app.route('/do', methods = ['POST'])
def do():
result = requests.get('slow api')
return result.content
gunicorn server:app -k gevent -w 4
- Was erwartest du, was hier geschehen würde? Sie können nicht wieder irgendetwas an den client, wenn Sie noch nicht erhalten haben es noch
- Ich hatte erwartet, um es async, so dass, wenn es darauf wartet, dass der super-slow-api die cpu-Leistung kann verwendet werden, zu verarbeiten eingehender Anforderungen an, die können möglicherweise gehen den anderen Weg. (Da ich davon ausgehe mit dieser Anwendung erhalten Sie viele andere verschiedene eingehende Anfragen)
- Das bedeutet nicht, was Sie denken, es bedeutet. Und Gunicorn sollte der Umgang mit diesem für Sie, könnten Sie testen, um sicherzustellen, dass nur durch das hinzufügen einer
time.sleep(30)
drin, denke ich. Es heißt, der Reaktor-Muster, aber Gunicorn ermöglicht es dem client, um eine Verbindung herzustellen, und dann geht aus der Anfrage an einen worker. Wenn der worker beendet ist, die Daten zurück, die aus der Arbeiter-und steckt es dann zurück in den pool. Ich bin mir nicht sicher, ob es startet eine neue Arbeiter, wenn alle die bestehenden ausgelastet sind, obwohl. - Ich bin immer noch lernen, aber ich erwarte ausgeführt Gunicorn sollte so etwas wie
gunicorn server:app -k gevent -w 4
aber ich bin mir wirklich nicht sicher. - meinst du, dass mit dem aktuellen code, den ich oben gepostet, wenn eine konkrete Anfrage, wartet auf die langsamen api für die Antwort, es wird nur die cpu-Leistung zu verarbeiten, andere eingehende Anfragen an den application server?
- Naja die CPU sicher, dass Ihr Betriebssystem, das behandeln, wenn der zugrunde liegende socket hat eine
.read
das OS wird sagen, "Oh, süße, dieser Prozess ist blockiert, laß mich etwas anderes tun". - Alles was ich will ist, zu erreichen, so viel rps, wie möglich, ich hatte die Erfahrung, dass langsam blocking IO wird deutlich verringern die rps mein application server verarbeiten kann, und ich möchte vermeiden, dass (vielleicht mit gevent?)
- Lassen Sie uns weiter, diese Diskussion im chat.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie die Bereitstellung Ihres Flask-Anwendung mit gunicorn, es ist schon nicht blockieren. Wenn ein client wartet auf eine Antwort von einem Ihrer Ansichten, kann ein anderer client eine Anfrage, um die gleiche Ansicht, ohne ein problem. Es werden mehrere Mitarbeiter Prozess mehrere Anforderungen gleichzeitig. Keine Notwendigkeit, den code ändern, damit dies funktioniert. Dies gilt auch für so ziemlich jede Flasche die option Bereitstellung.
requests.get
Blöcke, aber diese Aktion geschieht in einer solchen Weise, dass ein anderer client immer noch Zugriff auf die gleiche Ansicht, wie ich glaube, OP ' s Hauptanliegen. Sie können ein api-Aufruf, nicht blockierende, auch das hilft aber nicht, weil Sie nicht in der Lage sein, etwas zurückzugeben an den client, bis er abgeschlossen ist, sowieso.gunicorn ... --timeout 60
. Standardwert ist 30 Sekunden. stackoverflow.com/questions/6816215/...Zuerst ein wenig hintergrund, Ein blockierenden socket ist die Standard-Art von Buchse, sobald Sie beginnen, Lesen Sie Ihre app oder thread nicht wieder die Kontrolle, bis die Daten tatsächlich gelesen, oder Sie sind getrennt. Dies ist, wie
python-requests
arbeitet standardmäßig. Es ist ein spin-off namensgrequests
bietet non-blocking liest.Quelle: https://docs.python.org/2/howto/sockets.html
Er geht auch auf zu sagen:
Aber möchten Sie eine ganze Menge von Komplexität in Ihrem Blick, indem er es spawnen es eigene threads. Besonders, wenn gunicorn als async-workers?
und
So, um zu schneiden eine lange Geschichte kurz zu, ändern Sie nichts! Lass es einfach sein. Wenn Sie änderungen an alle, lassen Sie es sich vorstellen-caching. Erwägen Sie die Verwendung Cache-control eine Erweiterung empfohlen von python-requests-Entwickler.
Können Sie
grequests
. Es können andere greenlets zu laufen, während der Antrag gestellt wird. Es ist kompatibel mit denrequests
Bibliothek und gibt einenrequests.Response
Objekt. Die Verwendung ist wie folgt:Edit: ich habe einen test und sah, dass die Zeit nicht besser mit grequests seit gunicorn ist gevent Arbeiter schon führt monkey-patching, wenn es initialisiert wird: https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/ggevent.py#L65