Ich verwende eine Flask / Gunicorn Python-App auf einem Heroku Cedar-Prüfstand. Die App kehrt JSON responses
zu ihren Kunden zurück (es ist API server
wirklich eine).
Hin und wieder erhalten Clients 0-Byte-Antworten. Ich gebe sie jedoch nicht zurück. Hier ist ein Ausschnitt aus dem Protokoll meiner App:
14. März 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 app [web.1] [2013-03-14 13:13:31 UTC] 10.104.41.136 apisrv - api_get_credits_balance (): session_token = [MASKED ]]
In der ersten Zeile oben beginne ich mit der Bearbeitung der Anfrage.
14. März 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 app [web.1] [2013-03-14 13:13:31 UTC] 10.104.41.136 apisrv 1252148511 api_get_credits_balance (): return [{' Credits_Balance ': 0}]
In der zweiten Zeile gebe ich einen Wert zurück (an Flask - es ist ein Flask "Response" -Objekt).
14. März 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 app [web.1] 10.104.41.136 - - [14 / Mar / 2013: 13: 13: 31] POST / get_credits_balance? Session_token = MASKED HTTP / 1.1 "200 22" - "Appcelerator Titanium / 3.0.0.GA (iPhone / 6.1.2; iPhone OS; en_US;)"
Die dritte Zeile ist Gnicorns, in der Sie sehen können, dass das Gunicorn den 200-Status und den 22-Byte-HTTP-Body (" 200 22
") erhalten hat.
Der Client hat jedoch 0 Bytes. Hier ist das Heroku-Router-Protokoll:
14. März 13:13:30 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 heroku [router] at = info method = POST path = / get_credits_balance? Session_token = MASKED host = matchspot-apisrv.herokuapp.com fwd = "66.87. 116.128 "dyno = web.1 queue = 0 wait = 0ms connect = 1ms service = 19ms status = 200 bytes = 0
Warum gibt Gunicorn 22 Bytes zurück, aber Heroku sieht 0 und gibt tatsächlich 0 Bytes an den Client zurück? Ist das ein Heroku-Fehler?
Antworten:
Ich weiß, dass ich hier als etwas abseits der Mauer betrachtet werden kann, aber es gibt noch eine andere Option.
Wir wissen, dass es von Zeit zu Zeit einen Fehler gibt, der während des Transports auftritt. Wir wissen, dass wir derzeit nicht viel tun können, um das Problem zu stoppen. Wenn Sie nur die API bereitstellen, hören Sie auf zu lesen. Wenn Sie jedoch auch den Client schreiben, fahren Sie fort.
Der Fehler ist ein bekannter Fall und eine bekannte Ursache. Das Ergebnis eines leeren Rückgabewerts bedeutet, dass ein Fehler aufgetreten ist. Der Wert ist jedoch verfügbar und wurde abgerufen, berechnet, was auch immer ... Mein Instinkt als Entwickler wäre es, ein leeres Ergebnis als HTTP-Fehler zu behandeln und das erneute Senden der Daten anzufordern. Sie können dann die erneut gesendeten Anforderungen verfolgen und sehen, wie oft dies geschieht.
Ich würde vorschlagen (obwohl Sie mich als die Art von Entwickler betrachten, die auch daran denkt), dass Sie die Anforderungen zählen und einen vernünftigen Wert für die Antwort "Netzwerkfehler" an den Benutzer festlegen. Mein Instinkt wäre, es sofort noch einmal zu versuchen und dann eine Weile zu warten, bevor ich es noch einmal versuche.
Nach dem, was Sie beschreiben, würde der erste Wiederholungsversuch die Daten wahrscheinlich richtig erfassen. Dies kann natürlich bedeuten, dass ältere Anforderungen einige Minuten im Cache bleiben oder die Anforderung ein zweites Mal ausgeführt wird, je nachdem, was am besten geeignet erscheint.
Dies würde auch eine beliebige Anzahl anderer Punkt-zu-Punkt-Netzwerkfehler umgehen und die App selbst bei Verbindungsproblemen weitaus robuster machen.
Ich weiß, dass unser Instinkt als Entwickler darin besteht, den bekannten Fehler zu beheben, aber manchmal ist es besser, auf ein System hinzuarbeiten, das trotz Fehlern funktioniert. Das heißt, es tut nie weh, Fehler und Probleme zu protokollieren und sie trotzdem zu beheben.
quelle