Saya menjalankan aplikasi
gunicorn -w 2 -b ' localhost:8585 ' --timeout=200 --certfile=crt.crt --keyfile=key.key service:app
Dan saya mendapatkan yang berikut, tetapi saya tidak selalu mendapatkan jawaban seperti itu, sebagian besar permintaan ditangani dengan benar, tetapi terkadang terjadi kesalahan
[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
Dari ingatan saya, kesalahan ini terjadi ketika klien mencoba terhubung tanpa SSL. Mungkinkah itu yang terjadi pada Anda?
Saya melihat posting Anda tentang masalah lain yang saya tutup. Saya minta maaf jika komentar saya bukan penyebabnya.
Apakah ada pola di mana permintaan gagal dengan cara ini?
@usmetanina klien seperti apa yang terhubung ke Gunicorn juga? APAKAH Anda memiliki opsi SSL yang digunakan secara eksplisit untuk menghubungkannya?
apakah ini sudah terpecahkan? @usmetanina , karena saya memiliki masalah yang persis sama
@benoitc Saya sering melihat kesalahan persis @usmetanina menggunakan python3.6 dan gunicorn 19.9.0
.
Saya menggunakan informasi di bawah ini untuk memulai gunicorn dengan aplikasi labu yang berjalan di dalam wadah buruh pelabuhan.
gunicorn --workers=3 --bind=0.0.0.0:8000 --config=gunicorn_config.py --preload main
File konfigurasi terlihat seperti ini (domain-with-cert.com tentu saja adalah pengganti untuk nama domain yang sebenarnya):
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'
Setiap pemikiran tentang debugging ini akan sangat membantu. Jika Anda membutuhkan info lebih lanjut, beri tahu saya.
@willpatera , lihat komentar saya:
Dari ingatan saya, kesalahan ini terjadi ketika klien mencoba terhubung tanpa SSL. Mungkinkah itu yang terjadi pada Anda?
@tilgovi saya melihat komentar di atas. Saya cukup yakin bahwa klien terhubung melalui SSL. Ada saran debug?
@willpatera Saya akan mengatakan, nyalakan log akses dan lihat apakah Anda dapat menentukan permintaan mana yang menyebabkan masalah. Jika Anda memiliki proxy terbalik di depan gunicorn, pastikan ia memiliki log akses sehingga Anda mungkin dapat melihat permintaan mana yang menyebabkan kesalahan dengan gunicorn meskipun gunicorn tidak pernah mencatatnya.
@tilgovi Saya mengalami masalah yang sama. Harus mengedit sedikit informasi berikut karena salah:
Permintaan yang dilakukan kepada gunicorn selalu merupakan permintaan yang sama persis (tetapi dengan badan yang berbeda). Jadi tidak ada keraguan bahwa itu adalah https dan bukan http.
Apa yang saya perhatikan adalah bahwa itu selalu terjadi ketika jumlah permintaan naik. Ketika server sedang sibuk, tampaknya ada masalah dalam menangani permintaan dengan benar.
Mungkin ini ada hubungannya dengan para pekerja atau semacamnya? Jika Anda memiliki saran konfigurasi, saya dengan senang hati ingin mengujinya.
Hai guys, saya masih mencari cara untuk menyelesaikan ini. Saat ini satu-satunya pilihan yang kami miliki adalah menurunkan versi ke HTTP biasa, yang tidak layak sama sekali.
Saya pernah menyaksikan hal yang sama. Memiliki server produksi yang menjalankan Gunicorn + Flask (di belakang penyeimbang beban) yang berfungsi dengan baik selama berbulan-bulan, lalu tiba-tiba setiap permintaan menghasilkan kesalahan ini hingga saya memulai ulang Gunicorn:
[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
Tidak ada dalam log sebelum kesalahan ini yang menunjukkan pemicunya.
Ini dengan Gunicorn 19.9.0 berjalan dengan 3 pekerja di server berinti tunggal.
Karena ini adalah pertama kalinya saya melihat masalah ini, saya tidak bisa berjanji untuk mereproduksinya. Namun, jika ada jenis logging atau kode diagnostik lain yang ingin saya tambahkan di server kami yang mungkin memberikan beberapa informasi berguna jika hal ini terjadi lagi, saya setuju.
Apakah LB Anda memanggil titik akhir tertentu? Bagaimana cara menjawab permintaan LB?
Ketika saya mengatakan "Load Balancer", saya seharusnya mengatakan CDN atau lapisan caching. Khususnya: ini adalah Amazon Cloudfront. Itu hanya meneruskan permintaan ke server Gunicorn kami (berjalan pada instans EC2) dan menyimpan hasil untuk sementara waktu.
hrm tidakkah seharusnya amazon cloudfront menghentikan permintaan ssl untuk Anda? @ExplodingCabbage . Mengapa gunicorn harus mendengarkan ssl di belakang?
@benoitc Jadi, ada dua lapisan dengan SSL yang terlibat dalam arsitektur. Anggota publik terhubung ke situs web kami melalui domain CloudFront kami melalui HTTPS, dan kemudian CloudFront membuat permintaan ke node backend kami yang menjalankan Gunicorn, juga menggunakan HTTPS (dengan nama domain dan sertifikat yang berbeda), menyimpan hasil cache, dan menyajikannya ke publik.
Saya kira mungkin Anda bertanya-tanya apa gunanya menggunakan SSL untuk permintaan internal kedua itu? Ini tentu saja tidak ada gunanya (walaupun mungkin tidak - itu menghentikan Amazon mengintip komunikasi kami di jaringan internal mereka, dan ada juga alasan peraturan saya tidak akan membahas mengapa, mengingat industri perusahaan saya, kami mungkin perlu memastikan bahwa kami punya enkripsi sepanjang jalan di sepanjang pipa). Entah sia-sia atau tidak, kami melakukannya. \_(ツ)_/¯
mungkinkah cloudfront mengirim ke titik akhir Anda permintaan HTTP biasa? Jika Anda memiliki akses ke log cloudfront, Anda seharusnya dapat melihatnya.
@benoitc Saya tidak berpikir CloudFront memperlihatkan log apa pun yang akan berguna, tetapi saya yakin itu tidak mencoba terhubung melalui HTTP, karena:
@ExplodingCabbage ok saya akan melihatnya setelah 20.0.1 keluar. Satu hal terakhir, versi Python mana yang Anda gunakan?
3.6.8
Saya menyadari bahwa saya meninggalkan detail dari cerita saya di atas: sebelum memulai ulang Gunicorn, saya juga memperbarui sertifikat SSL yang digunakan Gunicorn dengan LetsEncrypt. Saya tidak berpikir untuk menyebutkan ini karena saya telah salah menyimpulkan kemarin bahwa tidak mungkin sertifikat akan kedaluwarsa pada hari kesalahan dimulai dan bahwa pembaruan sertifikat sebenarnya tidak relevan untuk memperbaiki masalah.
Namun, dari memeriksa beberapa log, saya sekarang menyadari bahwa kesalahan sebenarnya dimulai pada hari sertifikat sebelumnya akan kedaluwarsa.
Masih ada beberapa misteri di sini, dan beberapa ruang potensial untuk perbaikan (apa sebenarnya arti kesalahan ini, dan mengapa Gunicorn tidak dapat memberikan pesan yang lebih berguna?), tetapi narasi yang saya berikan sebelumnya - di mana kesalahan ini dimulai secara tiba-tiba tanpa penyebab yang jelas - tidak benar. Saya kira CloudFront memutuskan koneksi sebagai tanggapan atas melihat sertifikat kedaluwarsa dari server Gunicorn, dan bahwa Gunicorn, alih-alih dapat memahaminya dan melaporkannya secara bermakna, memungkinkan OSError tanpa pesan muncul.
Saya minta maaf karena tidak membuat bebek saya berturut-turut sebelum melaporkan. Di sisi lain, mungkin ini akan membuatnya lebih mudah untuk mereproduksi pengecualian ini sesuka hati jika Anda ingin mencoba dan menangani skenario dengan lebih elegan.
@ExplodingCabbage oh itu cukup menarik, itu harus direproduksi di beberapa titik. Terima kasih atas detail tambahannya!
Saya baru saja mengalami masalah yang sama dan saya agak yakin itu adalah konsekuensi dari semacam kelelahan sumber daya.
Bagi saya itu dipicu oleh lupa batas waktu pada panggilan pemblokiran dan permintaan yang menumpuk.
HTH
Halo! Saya mengalami masalah persis ini. Saya memiliki layanan gunicorn/flask yang berjalan di kluster ECS di belakang penyeimbang beban jaringan. Beberapa spesifikasi versi:
python - 3.7.4
gunicorn - 19.9.0
flask - 1.0.4
Layanan ini dapat menanggapi permintaan yang datang dari klien menggunakan TLS tanpa masalah, namun log saya dibanjiri dengan OSErrors. Sejauh yang saya tahu, ini dihasilkan dari permintaan pemeriksaan kesehatan yang berasal dari penyeimbang beban (TCP).
Saya dapat mereproduksi kesalahan secara lokal dengan membuka dan menutup koneksi TCP secara manual pada port mendengarkan (8000 dalam kasus ini):
$ nc -vz 127.0.0.1 8000
localhost [127.0.0.1] 8000 (irdmi) open
Yang mengakibatkan kesalahan berikut dilemparkan:
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
Semoga ini membantu!
Hmm, setelah beberapa penelitian tambahan, tampaknya ini sebenarnya adalah bug dalam cara pustaka python ssl
menangani EOF yang compang-camping di linux: https://bugs.python.org/issue31122
Seperti yang disebutkan oleh @shevisjohnson jika Anda menjalankan "nc -vz hostname port_no" kesalahan ini muncul.
Kami dapat menekan kesalahan ini dalam file log dengan menggunakan mekanisme logging di bawah ini.
$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]
Ini file pythonnya.
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!"
Semoga membantu.
Hanya butuh beberapa saat untuk menghasilkan reproduksi yang andal: menggunakan hey
untuk mengirim 100 permintaan bersamaan ke Gunicorn terbaru (20.0.4) menggunakan gthread
worker:
$ hey -n 100 -c 100 https://127.0.0.1:8000
```
$ aplikasi gunicorn
...
[2020-07-11 19:10:58 +0000] [3628247] [ERROR] Permintaan pemrosesan kesalahan soket.
Traceback (panggilan terakhir terakhir):
kembalikan diri._sslobj.read(len)
OSError: [Errno 0] Kesalahan
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 ""
Dalam hal ini membantu juga!
Jika akar masalahnya sebenarnya https://bugs.python.org/issue31122 :
Ini mempengaruhi organisasi saya di prod juga.
Saya perhatikan bahwa perbaikan bug mendarat di cabang 3,8 dan 3,9, tetapi mereka mempertimbangkan <= 3,7 EOL dan kami masih terjebak di 3,6 untuk saat ini. Apakah ada solusi yang diketahui untuk masalah ini saat ini di gunicorn itu sendiri? Apakah ada yang direncanakan?
Kami sedang mencari tahu apa yang bisa memanggil layanan begitu banyak untuk memicu ini, tapi saya hanya mencoba mencari tahu apa yang bisa dilakukan, karena ini menghasilkan lonjakan sumber daya yang besar pada node yang terpengaruh.
Selain komentar jriddy mengenai tidak ada niat untuk melakukan backport sebelum 3.8, jika ada orang lain yang mengalami masalah ini, perhatikan juga bahwa perbaikan diatur untuk disertakan dalam CPython 3.8.6 .
Mengalami kesulitan mengatakan dengan tepat dari mana traceback ini berasal - dalam kasus saya, menggunakan gevent
sebagai server aplikasi WSGI secara langsung, jadi dengan asumsi itu adalah panggilan logging di suatu tempat di dalam gevent/greenlet, tetapi belum dapat menemukannya. Untuk Gunicorn, itu terjadi di sini, untuk pekerja sinkron:
Dalam kasus Gunicorn, jika Anda hanya khawatir tentang kebisingan di log, mungkin dapat melakukan sesuatu seperti:
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())
Masalah gevent terkait: https://github.com/gevent/gevent/issues/1671
Komentar yang paling membantu
Hmm, setelah beberapa penelitian tambahan, tampaknya ini sebenarnya adalah bug dalam cara pustaka python
ssl
menangani EOF yang compang-camping di linux: https://bugs.python.org/issue31122