Ich führe die App aus
gunicorn -w 2 -b ' localhost:8585 ' --timeout=200 --certfile=crt.crt --keyfile=key.key service:app
Und ich bekomme folgendes, aber ich bekomme nicht immer eine solche Antwort, die meisten Anfragen werden korrekt behandelt, aber manchmal tritt ein Fehler auf
[2018-05-08 14:53:36 +0500] [11227] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/gunicorn/workers/sync.py", line 134, in handle
req = six.next(parser)
File "/usr/lib/python3/dist-packages/gunicorn/http/parser.py", line 41, in __next__
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
File "/usr/lib/python3/dist-packages/gunicorn/http/message.py", line 153, in __init__
super(Request, self).__init__(cfg, unreader)
File "/usr/lib/python3/dist-packages/gunicorn/http/message.py", line 53, in __init__
unused = self.parse(self.unreader)
File "/usr/lib/python3/dist-packages/gunicorn/http/message.py", line 165, in parse
self.get_data(unreader, buf, stop=True)
File "/usr/lib/python3/dist-packages/gunicorn/http/message.py", line 156, in get_data
data = unreader.read()
File "/usr/lib/python3/dist-packages/gunicorn/http/unreader.py", line 38, in read
d = self.chunk()
File "/usr/lib/python3/dist-packages/gunicorn/http/unreader.py", line 65, in chunk
return self.sock.recv(self.mxchunk)
File "/usr/lib/python3.5/ssl.py", line 922, in recv
return self.read(buflen)
File "/usr/lib/python3.5/ssl.py", line 799, in read
return self._sslobj.read(len, buffer)
File "/usr/lib/python3.5/ssl.py", line 585, in read
v = self._sslobj.read(len)
OSError: [Errno 0] Error
Aus meiner Erinnerung tritt dieser Fehler auf, wenn ein Client versucht, eine Verbindung ohne SSL herzustellen. Könnte das bei dir der Fall sein?
Ich sehe Ihren Beitrag zu dem anderen Problem, das ich geschlossen habe. Ich entschuldige mich, wenn mein Kommentar nicht die Ursache ist.
Gibt es ein Muster, nach dem Anfragen auf diese Weise fehlschlagen?
@usmetanina Welche Art von Clients verbinden sich auch mit Gunicorn? Haben Sie SSL-Optionen, die explizit verwendet werden, um eine Verbindung herzustellen?
ist das schon gelöst? @usmetanina , weil ich genau das gleiche Problem habe
@benoitc Ich sehe @usmetanina ‚genaue Fehler s häufig mit python3.6 und gunicorn 19.9.0
.
Ich verwende die folgenden Informationen, um gunicorn mit einer Flaschen-App zu starten, die in einem Docker-Container ausgeführt wird.
gunicorn --workers=3 --bind=0.0.0.0:8000 --config=gunicorn_config.py --preload main
Die Konfigurationsdatei sieht so aus (domain-with-cert.com ist natürlich ein Platzhalter für den eigentlichen Domainnamen):
workers = 3
bind = '0.0.0.0:443'
certfile = '/etc/letsencrypt/live/domain-with-cert.com/fullchain.pem'
keyfile = '/etc/letsencrypt/live/domain-with-cert.com/privkey.pem'
Alle Gedanken zur Fehlersuche wären hilfreich. Wenn Sie weitere Informationen benötigen, lassen Sie es mich einfach wissen.
@willpatera , siehe mein Kommentar:
Aus meiner Erinnerung tritt dieser Fehler auf, wenn ein Client versucht, eine Verbindung ohne SSL herzustellen. Könnte das bei dir der Fall sein?
@tilgovi Ich habe den obigen Kommentar gesehen. Ich bin mir ziemlich sicher, dass der Client über SSL eine Verbindung herstellt. Irgendwelche Debugging-Vorschläge?
@willpatera Ich würde sagen, schalten Sie die Zugriffsprotokolle ein und sehen Sie, ob Sie feststellen können, welche Anfrage das Problem verursacht. Wenn Sie einen Reverse-Proxy vor gunicorn haben, stellen Sie sicher, dass dieser über Zugriffsprotokolle verfügt, damit Sie möglicherweise sehen können, welche Anforderung einen Fehler bei gunicorn verursacht, auch wenn gunicorn es nie protokolliert.
@tilgovi Ich habe die gleichen Probleme. Musste die folgenden Informationen etwas bearbeiten, da sie falsch waren:
Die Anfrage an gunicorn ist immer die gleiche Anfrage (aber mit einem anderen Körper). Es besteht also kein Zweifel, dass es sich um https und nicht um http handelt.
Was mir auffällt, ist, dass es immer passiert, wenn die Anzahl der Anfragen steigt. Wenn der Server beschäftigt ist, scheint er Probleme zu haben, die Anforderungen richtig zu verarbeiten.
Hat das vielleicht mit den Arbeitern zu tun oder so? Wenn Sie Konfigurationsvorschläge haben, würde ich diese gerne testen.
Hallo Leute, ich suche noch nach einer Lösung für das Problem. Derzeit ist die einzige Option, die wir haben, ein Downgrade auf reines HTTP, was überhaupt nicht machbar ist.
Ich habe dasselbe erlebt. Hatte einen Produktionsserver mit Gunicorn + Flask (hinter einem Load Balancer), der monatelang einwandfrei funktionierte, ergab plötzlich jede Anfrage diesen Fehler, bis ich Gunicorn neu startete:
[2019-11-21 07:27:36 +0000] [24245] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/sync.py", line 134, in handle
req = six.next(parser)
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/parser.py", line 41, in __next__
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/message.py", line 181, in __init__
super(Request, self).__init__(cfg, unreader)
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/message.py", line 54, in __init__
unused = self.parse(self.unreader)
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/message.py", line 193, in parse
self.get_data(unreader, buf, stop=True)
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/message.py", line 184, in get_data
data = unreader.read()
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/unreader.py", line 38, in read
d = self.chunk()
File "/usr/local/lib/python3.6/dist-packages/gunicorn/http/unreader.py", line 65, in chunk
return self.sock.recv(self.mxchunk)
File "/usr/lib/python3.6/ssl.py", line 997, in recv
return self.read(buflen)
File "/usr/lib/python3.6/ssl.py", line 874, in read
return self._sslobj.read(len, buffer)
File "/usr/lib/python3.6/ssl.py", line 633, in read
v = self._sslobj.read(len)
OSError: [Errno 0] Error
Nichts in den Protokollen vor diesen Fehlern weist darauf hin, was der Auslöser gewesen sein könnte.
Dies war mit Gunicorn 19.9.0, das mit 3 Arbeitern auf einem Single-Core-Server lief.
Da ich dieses Problem zum ersten Mal sehe, kann ich nicht versprechen, dass ich es jemals reproduzieren werde. Wenn es jedoch irgendeine Art von Protokollierung oder anderen Diagnosecode gibt, der möchte, dass ich auf unserem Server einfüge, der einige nützliche Informationen für den Fall liefert, dass dies erneut passiert, bin ich ganz Ohr.
Ruft Ihr LB einen bestimmten Endpunkt an? Wie reagiert sie auf die LB-Anfrage?
Wenn ich "Load Balancer" sagte, hätte ich wirklich CDN oder Caching-Layer sagen sollen. Konkret: Es ist Amazon Cloudfront. Es leitet nur Anfragen an unseren Gunicorn-Server (der auf einer EC2-Instanz läuft) weiter und speichert die Ergebnisse für eine Weile.
hrm sollte nicht amazon cloudfront die ssl-Anfrage für dich beenden? @Explodierender Kohl . Warum muss gunicorn auf ssl hinter sich hören?
@benoitc Es gibt also zwei Schichten mit SSL, die an der Architektur beteiligt sind. Mitglieder der Öffentlichkeit stellen eine Verbindung zu unserer Website über unsere CloudFront-Domain über HTTPS her, und dann stellt CloudFront eine Anfrage an unseren Backend-Knoten, auf dem Gunicorn ausgeführt wird, ebenfalls unter Verwendung von HTTPS (mit einem anderen Domainnamen und Zertifikat), speichert das Ergebnis im Cache und liefert es an die öffentlich.
Vielleicht fragen Sie sich, welchen Sinn es hat, SSL für diese zweite interne Anfrage zu verwenden? Es ist sicherlich fraglich, ob es sinnlos ist (obwohl es möglicherweise nicht - es verhindert, dass Amazon in unseren Kommunikationen in ihrem internen Netzwerk herumschnüffelt, und es gibt auch regulatorische Gründe, auf die ich nicht eingehen werde, warum wir angesichts der Branche meines Unternehmens möglicherweise sicherstellen müssen, dass wir Verschlüsselung entlang der Pipeline). Ob sinnlos oder nicht, wir machen es. ¯\_(ツ)_/¯
Könnte es sein, dass Cloudfront eine einfache HTTP-Anfrage an Ihren Endpunkt sendet? Wenn Sie Zugriff auf die Cloudfront-Protokolle haben, sollten Sie diese sehen können.
@benoitc Ich glaube nicht, dass CloudFront irgendwelche Protokolle
@ExplodingCabbage ok Ich werde es mir ansehen, nachdem die 20.0.1 herausgekommen ist. Eine letzte Sache, welche Version von Python verwenden Sie?
3.6.8
Mir ist klar, dass ich ein Detail aus meiner obigen Geschichte ausgelassen habe: Vor dem Neustart von Gunicorn habe ich auch das SSL-Zertifikat aktualisiert, das Gunicorn mit LetsEncrypt verwendet. Ich hatte nicht daran gedacht, dies zu erwähnen, weil ich gestern fälschlicherweise zu dem Schluss gekommen war, dass ein Zertifikat am Tag des Fehlerbeginns auf keinen Fall abgelaufen wäre und die Zertifikatsaktualisierung für die Behebung des Problems tatsächlich nicht relevant gewesen sei.
Beim Überprüfen einiger Protokolle erkenne ich jedoch, dass die Fehler tatsächlich an dem Tag begannen, an dem ein vorheriges Zertifikat ablaufen sollte.
Hier gibt es immer noch ein Rätsel und ein potenzielles Verbesserungspotenzial (was genau bedeutet dieser Fehler und warum kann Gunicorn keine nützlichere Nachricht geben?), aber die Erzählung, die ich zuvor gegeben habe - in der dieser Fehler aus heiterem Himmel begann ohne ersichtlichen Grund - ist nicht richtig. Ich würde vermuten, dass CloudFront die Verbindung als Reaktion auf ein abgelaufenes Zertifikat vom Gunicorn-Server beendet hat, und dass Gunicorn, anstatt dies zu verstehen und sinnvoll zu melden, einen nachrichtenlosen OSError aufblähen lässt.
Ich entschuldige mich dafür, dass ich meine Enten nicht hintereinander habe, bevor ich mich melde. Auf der anderen Seite ist es vielleicht einfacher, diese Ausnahme nach Belieben zu reproduzieren, wenn Sie versuchen möchten, das Szenario eleganter zu handhaben.
@ExplodingCabbage oh das ist
Ich bin gerade reproduzierbar auf dasselbe Problem gestoßen und bin mir ziemlich sicher, dass es die Folge einer Art von Ressourcenerschöpfung ist.
Bei mir wurde es ausgelöst, indem ich eine Zeitüberschreitung bei einem blockierenden Anruf vergaß und sich Anfragen häuften.
HTH
Hallo! Ich habe genau dieses Problem. Ich habe einen Gunicorn/Flask-Dienst, der auf einem ECS-Cluster hinter einem Netzwerk-Load-Balancer ausgeführt wird. Einige Versionsdetails:
python - 3.7.4
gunicorn - 19.9.0
flask - 1.0.4
Der Dienst kann problemlos auf Anfragen eines Clients reagieren, der TLS verwendet, aber meine Protokolle werden mit OSErrors überflutet. Soweit ich das beurteilen kann, resultieren diese aus den Health Check-Anfragen des Load Balancer (TCP).
Ich konnte den Fehler lokal reproduzieren, indem ich eine TCP-Verbindung manuell auf dem Listening-Port (in diesem Fall 8000) öffnete und schloss:
$ nc -vz 127.0.0.1 8000
localhost [127.0.0.1] 8000 (irdmi) open
Was dazu führte, dass der folgende Fehler geworfen wurde:
Traceback (most recent call last):
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/workers/sync.py" line 134 in handle
req = six.next(parser)
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/parser.py" line 41 in __next__
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/message.py" line 181 in __init__
super(Request, self).__init__(cfg, unreader)
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/message.py" line 54 in __init__
unused = self.parse(self.unreader)
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/message.py" line 193 in parse
self.get_data(unreader, buf, stop=True)
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/message.py" line 184 in get_data
data = unreader.read()
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/unreader.py" line 38 in read
d = self.chunk()
File "/nix/store/nh3v0c2nipihwblkdn0mh2kqyv3jq9nz-python3-3.7.4-env/lib/python3.7/site-packages/gunicorn/http/unreader.py" line 65 in chunk
return self.sock.recv(self.mxchunk)
File "/nix/store/azwzsm1pkbzjxpkiq88w68p4jdghgasl-python3-3.7.4/lib/python3.7/ssl.py" line 1056 in recv
return self.read(buflen)
File "/nix/store/azwzsm1pkbzjxpkiq88w68p4jdghgasl-python3-3.7.4/lib/python3.7/ssl.py" line 931 in read
return self._sslobj.read(len)
OSError: [Errno 0] Error
Hoffe das hilft!
Hmm, nach einigen zusätzlichen Recherchen scheint dies tatsächlich ein Fehler in der Art und Weise zu sein, wie die Python-Bibliothek ssl
zerlumpte EOFs unter Linux behandelt: https://bugs.python.org/issue31122
Wie von @shevisjohnson erwähnt, erscheint dieser Fehler, wenn Sie "nc -vz hostname port_no" ausführen.
Wir können diesen Fehler in der Protokolldatei unterdrücken, indem wir den folgenden Protokollierungsmechanismus verwenden.
$cat Logging_config.yml
version: 1
formatters:
simple:
format: " %(asctime)s || %(name)s || %(levelname)s || %(message)s"
test_api:
format: "[%(asctime)s] [%(process)s] [%(levelname)s] %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
test_api_file_handler:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: test_api
filename: logs/test.log
maxBytes: 2000000000
backupCount: 1
encoding: utf8
loggers:
test_api:
level: DEBUG
handlers: [test_api_file_handler]
propagate: 0
root:
level: DEBUG
handlers: [console]
Hier ist die Python-Datei.
import logging
import yaml
from flask import Flask
app = Flask(__name__)
def logSetter(logger_name:str) -> logging:
with open("logging_config.yml", 'r') as f:
config = yaml.safe_load(f)
logging.config.dictConfig(config)
logger = logging.getLogger(logger_name)
return logger
logger=logSetter(logger_name="test_api")
@app.route("/api/test")
def hello():
app.logger.info("hey from api")
return "Hello from Python!"
Ich hoffe es hilft.
Es dauerte nur einen Moment, um eine zuverlässige Reproduktion zu finden: Verwenden Sie hey
, um 100 gleichzeitige Anfragen an das neueste Gunicorn (20.0.4) mit dem gthread
Worker zu senden:
$ hey -n 100 -c 100 https://127.0.0.1:8000
```
$ gunicorn app:app -k gthread --certfile=... --keyfile=...
...
[2020-07-11 19:10:58 +0000] [3628247] [ERROR] Socket-Fehler bei Verarbeitungsanfrage.
Traceback (letzter Anruf zuletzt):
return self._sslobj.read(len)
OSFehler: [Errno 0] Fehler
Using a Debian 9 / Linux 4.14.67 based environment.
The WSGI app to reproduce need not be anything beyond:
```python
# app.py
def app(environ, start_response):
start_response("200 OK", [])
return ""
Falls das auch hilft!
Wenn die Ursache tatsächlich https://bugs.python.org/issue31122 ist :
Dies wirkt sich auch auf meine Organisation in der Produktion aus.
Mir ist aufgefallen, dass der Bugfix in den Zweigen 3.8 und 3.9 gelandet ist, aber sie erwägen <= 3.7 EOL und wir bleiben vorerst immer noch bei 3.6. Gibt es derzeit in gunicorn selbst eine bekannte Problemumgehung für dieses Problem? Ist etwas geplant?
Wir untersuchen, was den Dienst so oft aufrufen könnte, um dies auszulösen, aber ich versuche nur herauszufinden, was getan werden könnte, da dies zu enormen Ressourcenspitzen auf den betroffenen Knoten führt.
Zusätzlich zu jriddys Kommentar, dass keine Absicht besteht, vor Version 3.8 zurück zu portieren, beachten Sie, dass der Fix , falls jemand anderes dieses Problem hat,
Ich habe Probleme, genau zu sagen, woher dieser Traceback stammt - in meinem Fall, indem ich gevent
direkt als WSGI-App-Server verwende. Für Gunicorn passiert es hier, für Synchronarbeiter:
Wenn Sie sich im Fall von Gunicorn nur Sorgen um das Rauschen in Protokollen machen, können Sie Folgendes tun:
import logging
class HandshakeFilter(logging.Filter):
# example: https://docs.python.org/3/howto/logging-cookbook.html
# I have not tested this
def filter(self, record):
return "socket error processing request" in record.msg.casefold()
logging.getLogger("gunicorn").addFilter(HandshakeFilter())
Zugehöriges gevent-Problem: https://github.com/gevent/gevent/issues/1671
Hilfreichster Kommentar
Hmm, nach einigen zusätzlichen Recherchen scheint dies tatsächlich ein Fehler in der Art und Weise zu sein, wie die Python-Bibliothek
ssl
zerlumpte EOFs unter Linux behandelt: https://bugs.python.org/issue31122