Gunicorn: يقوم "عامل التشغيل" بالتكرار اللانهائي على الرغم من عدم وجود إشارات خروج

تم إنشاؤها على ١١ ديسمبر ٢٠١٧  ·  65تعليقات  ·  مصدر: benoitc/gunicorn

أحاول إعداد gunicorn على Docker. إنه يعمل جيدًا محليًا ، وصورة الإنتاج هي نفسها تمامًا الصورة المحلية ، لكني أتلقى هذا السلوك الغريب في محرك Docker للإنتاج:

ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Starting gunicorn 19.7.1
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] Arbiter booted
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Using worker: sync
ml-server_1     | [2017-12-11 13:18:50 +0000] [8] [INFO] Booting worker with pid: 8
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] 1 workers
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:54 +0000] [11] [INFO] Booting worker with pid: 11
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:58 +0000] [14] [INFO] Booting worker with pid: 14
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:19:02 +0000] [17] [INFO] Booting worker with pid: 17
ml-server_1     | Using TensorFlow backend.

يبدو أن gunicorn يقوم بتمهيد العمال كل 4-5 ثوانٍ ، على الرغم من عدم ظهور رسائل خطأ أو إشارات خروج. يستمر هذا السلوك إلى أجل غير مسمى حتى يتم إنهاؤه.

هل من الممكن أن يخرج العامل دون تسجيل أي شيء إلى stderr / stdout ، أو أن يقوم الحكم بتوليد العمال إلى ما لا نهاية؟

نظرًا لأنهم نفس صورة عامل الإرساء ، فإنهم يشغلون نفس الكود تمامًا ، على نفس البنية بالضبط ، لذلك أنا في حيرة من أمري ما يمكن أن يكون (خطأ؟). أي مساعدة موضع تقدير كبير!

Improvement help wanted

التعليق الأكثر فائدة

مجرد تحديث ، كانت المشكلة بالنسبة لي في الواقع خطأ في الذاكرة وتم إصلاحها عندما تم إصلاح مشكلة الذاكرة.

ال 65 كومينتر

قادني ssh -ing في حاوية Docker للعثور على هذا الخطأ:

Illegal instruction (core dumped)

ربما يجب أن تظهر أخطاء gunicorn مثل هذه الأخطاء بدلاً من ابتلاعها ، أو التعامل معها بشكل مختلف؟ لست متأكدًا ، فقط اعتقدت أنني سأطرح هذا لأنه قد يساعد شخصًا آخر!

شكرا للإبلاغ عن هذه المسألة!

إذا كان بإمكانك معرفة مكان حدوث ذلك ، فسيكون ذلك مفيدًا للغاية.

ربما يمكننا إضافة تسجيل عند خروج العمال. عادة ، يقوم العامل نفسه بتسجيل الدخول ، ولكن إذا تم قتله فجأة ، فلن يفعل ذلك.

لا داعى للقلق!

يبدو أن هناك مشكلة في Spacy والتي أضفتها للتو إلى هذا الموضوع: https://github.com/explosion/spaCy/issues/1589

على أي حال ، يتسبب في حدوث SIGILL كما يؤكد strace :

--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x7ff48bbe6cea} ---
+++ killed by SIGILL (core dumped) +++
Illegal instruction (core dumped)

أفترض أنه سيكون من الجيد أن يتمكن Gunicorn من تحديد هذا وتسجيل خطأ بدلاً من إعادة تشغيل العامل بشكل وهمي ، لكن tbh أعرف القليل جدًا عن كيفية عمل رموز الخروج!

من المؤكد أن بعض رموز الخروج لها معاني خاصة ويمكننا على الأرجح تسجيلها.
http://tldp.org/LDP/abs/html/exitcodes.html

يبدو جيدا! بالإضافة إلى ذلك ، إذا لم يكن كود الخروج رمز خروج محجوز (مثل هذه الحالة) ، فسيكون من الرائع أن يتم تسجيل ذلك (بدون تفسير) لذلك من الواضح أن العامل قد أنهى بالفعل 🙂

لدي مشكلة مماثلة ، يقوم برنامج gunicorn بتمهيد العامل الجديد دائمًا عندما أقوم بتقديم طلب http. لا أحصل على أي رد ، إنه يعيد تشغيل العامل الجديد دائمًا. سجل Strace من طلبي http:

select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=510, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=32} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 510
lseek(8, 0, SEEK_CUR)                   = 0
close(8)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 840340})     = 1 (in [3], left {0, 840338})
read(3, ".", 1)                         = 1
read(3, 0x7f2682025fa0, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-q4aa72u7", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 8
fcntl(8, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-q4aa72u7", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-q4aa72u7")       = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(8, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(8, 0, SEEK_CUR)                   = 0
lseek(8, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 558
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 37381}[2017-12-28 17:50:23 +0000] [558] [INFO] Booting worker with pid: 558
) = 0 (Timeout)
select(4, [3], [], [], {1, 0}loading test-eu-ovh settings
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=499, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=31} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 499
lseek(7, 0, SEEK_CUR)                   = 0
close(7)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 450691})     = 1 (in [3], left {0, 450689})
read(3, ".", 1)                         = 1
read(3, 0x7f2682067de8, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-5x9a40ca", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 7
fcntl(7, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-5x9a40ca", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-5x9a40ca")       = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(7, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(7, 0, SEEK_CUR)                   = 0
lseek(7, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 579
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 8144}[2017-12-28 17:50:30 +0000] [579] [INFO] Booting worker with pid: 579
)  = 0 (Timeout)
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0

أواجه نفس المشكلة، gunicorn يتم تمهيد المتكررة في غضون ثوان ل sync نوع عامل. لا يساعد تعيين مهلة العامل على 900 .

في التحميل قبل الإجراء ، أقوم بتنزيل البيانات من AWS S3. يستغرق تنزيل الملفات المختلفة حوالي دقيقة و 10 ثوانٍ.

@ sara-02 ما هو سطر الأوامر الخاص بك لإطلاق Gunicorn؟

benoitc gunicorn --pythonpath /src -b 0.0.0.0:$SERVICE_PORT --workers=1 -k sync -t $SERVICE_TIMEOUT flask_endpoint:app
موجود هنا

@ sara-02 شكرا.

هل العمال القدامى غادروا حقًا أم أنهم يظلون متصلين بالإنترنت وينتج عمال جدد؟ ما الذي يظهره سجل التصحيح أيضًا؟

يتم خلط السجلات مع سجلات botocore ، لكنها شيء من هذا القبيل

[INFO] Booting worker with pid:  a
[INFO] Booting worker with pid:  b
[INFO] Booting worker with pid:  c

ولكن هل قتل العامل؟ ما إرجاع الأمر ps ax|grep gunicorn ؟

تضمين التغريدة
screenshot from 2018-07-05 19-14-00

على الرغم من ذلك ، هناك سؤال واحد ، لماذا نرى 2 gunicorn عمليات ، عندما يتم تعيين حد العامل على 1؟ سيد واحد وعامل واحد؟

هناك عملية حكم واحدة (رئيسية) وعمليات N عمال أيها :)

إذن أنت تقوم بتشغيل الأمر في كل مرة يقوم فيها العامل بالتمهيد ، أليس كذلك؟ إذا كان الأمر كذلك ، فيبدو أن العامل الأكبر سناً قد قُتل ، يتم تفريخ عامل جديد. وسوف التحقيق.

@ sara-02 شيء أخير ، هل يحدث هذا أيضًا في عامل ميناء؟

benoitc على docker-compose يعمل كما هو متوقع ، لكن عندما أضع نفس الكود على Openshift ، أرى هذا الخطأ. تم إصلاح زيادة متطلبات الذاكرة ، ولكن عندما أقوم بتشغيل التطبيق عبر docker-compose فإنه يستخدم ذاكرة أقل من limited .

مجرد تحديث ، كانت المشكلة بالنسبة لي في الواقع خطأ في الذاكرة وتم إصلاحها عندما تم إصلاح مشكلة الذاكرة.

تضمين التغريدة
أواجه نفس المشكلة أثناء محاولتي إنتاج 5 عمال غونيكورن في عامل الرصيف.
@ sara-02
كيف حددت سبب خطأ في الذاكرة؟

image

ساعدتني أشياء @ gulshan-gaurav:
لقد قمت بزيادة الذاكرة المخصصة لجهاز Pod الخاص بي وتوقفت عن الانهيار. ثانيًا ، قمنا بفحص سجلات Openshift Zabbix الخاصة بنا.

@ sara-02
حتى في قرص التدريج ، تبلغ مساحة الملفات + النماذج التي أقوم بتحميلها في الذاكرة 50 ميجابايت ، لذا يجب أن تكون سعة 2 جيجابايت من الذاكرة كافية لـ 5 عمال.

@ gulshan-gaurav ما هي القضية التي تواجهها؟ وجود 5 عمليات هناك تبدو جيدة ....

كان لي نفس القضية. لم أقم بتحديد المشكلة بالضبط ، ولكن تم حلها بمجرد أن قمت بالترقية من python 3.5 إلى 3.6.

أواجه نفس المشكلة في حاوية Docker. يواصل Gunicorn وضع عامل جديد في كل مرة أتصل فيها بنقطة نهاية تسبب الفشل ولكن لا يتم إخراج استثناء أو خطأ في ملفات سجل Gunicorn. يتم تسجيل الأشياء التي اخترت طباعتها ثم فجأة يقول ملف السجل "Booting worker with pid ..."

كانت إحدى الخطوات التي ساعدت هي إضافة متغير env PYTHONUNBUFERED. قبل ذلك ، حتى البيانات المطبوعة ستختفي ولن يتم حفظها في سجلات Gunicorn.

2 نقاط نهاية أخرى للتطبيق تعمل بشكل صحيح.

أقوم بتشغيل Gunicorn باستخدام: gunicorn run: app -b localhost: 5000 --enable-stdio-inheritance --error-logfile /var/log/gunicorn/error.log --access-logfile / var / log / gunicorn / access. سجل - التقاط - إخراج - تصحيح مستوى السجل

يتم تشغيل Python 3.6 بالفعل والتحقق من أن الذاكرة لا تبدو مشكلة.

تحرير: يبدو أنها كانت مشكلة في Python وليست خطأ Gunicorn. كانت بعض التناقضات في الإصدار تتسبب في موت بايثون دون أي أثر أثناء إجراء عملية معينة.

أواجه مشكلة مماثلة حيث تستمر العقدة العاملة في الظهور
Booting worker with pid: 17636 . لا أعرف ما إذا كانت تقتل عقدة العامل السابقة أم أن عقدة العامل السابقة لا تزال موجودة. لكن عدد العمال المذكورين في وسيطات سطر أوامر gunicorn هو 3 فقط - -workers=3 . كما أنني أستخدم الإصدار 3.7 من python

كان لدي عدم تطابق في تبعية scikit-Learn ، ولكن حتى بعد حل ذلك ، ما زلت أتلقى نفس العمال اللانهائيين القادمين. ما نوع الاختلافات في إصدار Python التي يجب أن أبحث عنها وكيف يمكنني التعرف عليها؟

أواجه نفس المشكلة داخل OpenShift.

image

كما ترى في الصورة ، أستخدم 6 عمال (كنت أحاول مع 3).
لقد قمت بزيادة ذاكرة الكبسولة ولم تنجح.

BuildConfig:

image

اي فكرة؟

شكرا

هل تقوم بتشغيل هذا خلف elb؟ لقد قمت بحل هذه المشكلة عن طريق وضع إدخال nginx بين elb و gunicorn

لديك نفس المشكلة.

flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Starting gunicorn 19.9.0
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Using worker: sync
flask_1  | [2019-02-23 09:08:17 +0000] [8] [INFO] Booting worker with pid: 8
flask_1  | [2019-02-23 09:08:19 +0000] [12] [INFO] Booting worker with pid: 12
flask_1  | [2019-02-23 09:08:19 +0000] [16] [INFO] Booting worker with pid: 16
flask_1  | [2019-02-23 09:08:20 +0000] [20] [INFO] Booting worker with pid: 20
flask_1  | [2019-02-23 09:08:21 +0000] [24] [INFO] Booting worker with pid: 24
flask_1  | [2019-02-23 09:08:22 +0000] [28] [INFO] Booting worker with pid: 28
flask_1  | [2019-02-23 09:08:23 +0000] [32] [INFO] Booting worker with pid: 32
flask_1  | [2019-02-23 09:08:25 +0000] [36] [INFO] Booting worker with pid: 36
flask_1  | [2019-02-23 09:08:26 +0000] [40] [INFO] Booting worker with pid: 40
flask_1  | [2019-02-23 09:08:27 +0000] [44] [INFO] Booting worker with pid: 44
flask_1  | [2019-02-23 09:08:29 +0000] [48] [INFO] Booting worker with pid: 48
flask_1  | [2019-02-23 09:08:30 +0000] [52] [INFO] Booting worker with pid: 52
flask_1  | [2019-02-23 09:08:31 +0000] [56] [INFO] Booting worker with pid: 56
flask_1  | [2019-02-23 09:08:33 +0000] [60] [INFO] Booting worker with pid: 60
flask_1  | [2019-02-23 09:08:34 +0000] [64] [INFO] Booting worker with pid: 64
flask_1  | [2019-02-23 09:08:35 +0000] [68] [INFO] Booting worker with pid: 68
flask_1  | [2019-02-23 09:08:36 +0000] [72] [INFO] Booting worker with pid: 72
flask_1  | [2019-02-23 09:08:37 +0000] [76] [INFO] Booting worker with pid: 76
flask_1  | [2019-02-23 09:08:38 +0000] [80] [INFO] Booting worker with pid: 80
flask_1  | [2019-02-23 09:08:40 +0000] [84] [INFO] Booting worker with pid: 84
flask_1  | [2019-02-23 09:08:41 +0000] [88] [INFO] Booting worker with pid: 88
flask_1  | [2019-02-23 09:08:42 +0000] [92] [INFO] Booting worker with pid: 92
flask_1  | [2019-02-23 09:08:44 +0000] [96] [INFO] Booting worker with pid: 96
flask_1  | [2019-02-23 09:08:45 +0000] [100] [INFO] Booting worker with pid: 100
flask_1  | [2019-02-23 09:08:45 +0000] [104] [INFO] Booting worker with pid: 104
flask_1  | [2019-02-23 09:08:46 +0000] [108] [INFO] Booting worker with pid: 108
flask_1  | [2019-02-23 09:08:47 +0000] [112] [INFO] Booting worker with pid: 112
flask_1  | [2019-02-23 09:08:48 +0000] [116] [INFO] Booting worker with pid: 116
flask_1  | [2019-02-23 09:08:49 +0000] [120] [INFO] Booting worker with pid: 120
flask_1  | [2019-02-23 09:08:50 +0000] [124] [INFO] Booting worker with pid: 124
flask_1  | [2019-02-23 09:08:52 +0000] [128] [INFO] Booting worker with pid: 128

هنا docker-compose.yml :

version: '3'
services:
  flask:
    build: .
    command: gunicorn -b 0.0.0.0:5000 hello:app --reload
    environment:
      - FLASK_APP=hello.py
      - FLASK_DEBUG=1
      - PYTHONUNBUFFERED=True
    ports:
      - "5000:5000"
    volumes:
      - ./:/root

ما هي صورة عامل الميناء الذي تستخدمه؟

تضمين التغريدة

[ec2-user@ip-172-31-85-181 web-services-course]$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
[ec2-user@ip-172-31-85-181 web-services-course]$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01

هنا روابط لـ:

اكتشفت أنه قد يكون بسبب نقص الذاكرة. يحتاج التطبيق إلى ذاكرة أكبر مما هو متاح.
لكنها مجرد افتراض

تمامًا كمعلومات: لقد لاحظت هذا السلوك بالضبط عندما يكون لدي gunicorn conf لـ 3 عمال ، لكنني قمت بنشر الكود في جهاز افتراضي باستخدام وحدة معالجة مركزية أساسية واحدة. بعد ذلك ، قمت بتغيير البيئة لاستخدام مركزين ، ومن الواضح أن المشكلة اختفت

لماذا "يغادر العامل" عند المستوى INFO فقط - لماذا يخرج العامل إلا نتيجة لخطأ؟ لقد استغرقت وقتًا طويلاً لأدرك أن خيوط عملي تم قتلها بواسطة نظام OOM killer ، مع عدم وجود أي شيء في السجلات باستثناء ، كما ذكر البعض الآخر أعلاه ، "Booting worker with pid" من وقت لآخر.

HughWarrington لأن خروج العامل ليس بالضرورة خطأ. يمكن إنهاء العمال بإشارات أو بخيارات مثل --max-requests .

HughWarrington يمكننا على الأرجح إضافة تسجيل الدخول إلى الحكم عندما يخرج عامل برمز خروج غير طبيعي.

يمكنك فتح تذكرة لذلك ، أو المساهمة في العلاقات العامة التي تضيف هذا الرمز إلى طريقة reap_workers .

واجهت نفس المشكلة ، وكان الحل هو زيادة حجم ذاكرة البود.

واجهت نفس المشكلة أثناء تشغيل Gunicorn على Docker بنموذج spaCy كبير ، فقد استمر في إعادة تشغيل العمال دون أي رسائل خطأ. الحل هو زيادة الذاكرة لحاوية Docker.

واجهت للتو هذه المشكلة اليوم على أحدث (19.9.0) gunicorn مع gevent (1.4.0) عمال يعملون على Kubernetes. التطبيق عبارة عن تطبيق Falcon وصورة Docker هي صورة Python الرسمية بعلامة 3.7.3 .

[2019-07-05 00:07:42 +0000] [8] [INFO] Starting gunicorn 19.9.0
[2019-07-05 00:07:42 +0000] [8] [INFO] Listening at: http://0.0.0.0:5000 (8)
[2019-07-05 00:07:42 +0000] [8] [INFO] Using worker: gevent
[2019-07-05 00:07:43 +0000] [35] [INFO] Booting worker with pid: 35
[2019-07-05 00:07:43 +0000] [36] [INFO] Booting worker with pid: 36
[2019-07-05 00:07:43 +0000] [37] [INFO] Booting worker with pid: 37
[2019-07-05 00:07:43 +0000] [38] [INFO] Booting worker with pid: 38
[2019-07-05 00:07:43 +0000] [41] [INFO] Booting worker with pid: 41
[2019-07-05 00:07:43 +0000] [43] [INFO] Booting worker with pid: 43
[2019-07-05 00:07:43 +0000] [45] [INFO] Booting worker with pid: 45
[2019-07-05 00:07:43 +0000] [49] [INFO] Booting worker with pid: 49
[2019-07-05 00:07:43 +0000] [47] [INFO] Booting worker with pid: 47
[2019-07-05 00:07:49 +0000] [53] [INFO] Booting worker with pid: 53
[2019-07-05 00:07:50 +0000] [54] [INFO] Booting worker with pid: 54
[2019-07-05 00:07:53 +0000] [57] [INFO] Booting worker with pid: 57
[...]

كان للجراب إعدادات الموارد التالية:

resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    cpu: 500m
    memory: 512Mi

مضاعفة كل شيء أصلحت المشكلة.

من الأشياء المثيرة للاهتمام التي لاحظناها أنه عند النظر إلى dmesg على الجهاز المضيف ، يمكننا أن نرى أنه segfault -ing عند libcrypto عند الوصول إلى الخادم باستخدام SSL

يبدو أن الذاكرة ليست مشكلة بالنسبة لي لأنني لا أحمل أي نموذج كبير في الذاكرة. يستمر العمال في الانهيار ولا يمكنني رؤية أي رسائل خطأ. هل هناك إصلاح لهذه؟

image

نفس المشكلة بالنسبة لي ، أي فكرة لإصلاحها؟ بيثون 3.6.3 مع جونيكورن 19.9.0

MrKiven ماذا يفعل التطبيق الخاص بك؟ هل تستخدم أشياء مثل الطلب؟

هل يمكن لشخص ما أن يوفر طريقة لإعادة إظهار المشكلة؟

إنه مدير للعديد من المكونات التي يتم تنفيذها في خط الأنابيب. قد يبدأ بعضهم طلبات HTTP لمكونات أخرى على نفس الجهاز أو على أجهزة بعيدة. يمكن تنفيذ بعض الوحدات النمطية لخط الأنابيب بالتوازي ولكن يتم تنفيذها باستخدام ThreadPoolExecutor. لا يستخدمون أي كائنات مشتركة ولكنهم يولدون فقط هياكل البيانات التي يتم تجميعها لاحقًا في كائن واحد ناتج.

لسوء الحظ ، لست متأكدًا مما إذا كان بإمكاني وضع مثال بسيط دون الكشف عن النظام الذي لدينا.

تقوم الطلبات بالكثير من الأشياء غير الآمنة باستخدام مؤشرات ترابط تؤدي أحيانًا إلى حدوث عملية جديدة. أنصح باستخدام عميل آخر. هل يمكنك لصق الأسطر التي تستخدمها على الأقل لتنفيذ طلب؟ هل تستخدم ميزة المهلة؟

يمكن أن يكون أحدهم:

try:
     resp = requests.post(self._endpoint, json=request_data)

     if resp.status_code != 200:
          logger.critical("[Error]: status code is {}".format(resp.status_code))
          return None

     response = resp.json()
     return {"intent": response["intent"], "intent_ranking": response["intent_ranking"]}
except ConnectionError as exc:
     logger.critical("[Exception] {}".format(str(exc)))
     return None

شكرا. سأحاول إنشاء بسيطة منه.

سيكون أمرًا رائعًا على أي حال إذا كان بإمكان شخص ما أن يرسل لنا تقريرًا يعيد إنتاج السلوك إما كمثال أو اختبار وحدة ، لذلك نتأكد من أننا نقوم بالفعل بإصلاح الشيء الصحيح.

لست متأكدًا مما إذا كان يمكن أن يساعد شخصًا ما ، لكنني واجهت نفس المشكلة أثناء تشغيل تطبيق flask webapp الذي تم إرساؤه وقمت بحله بتحديث الصورة الأساسية لملف dockerfile الخاص بي إلى python:3.6.9-alpine

أظهر Dmesg على المضيف خطأ segfault على lilibpython3.6m.so 1.0:

[626278.653010] gunicorn[19965]: segfault at 70 ip 00007f6423e7faee sp 00007ffc4e9a2a38 error 4 in libpython3.6m.so.1.0[7f6423d8a000+194000]

كانت صورة عامل الإرساء الخاصة بي مبنية على python:3.6-alpine وأقوم بعمل apk update والذي كان يقوم بتحديث python إلى 3.6.8.

كما قيل تغيير الصورة الأساسية إلى python:3.6.9-alpine حلها بالنسبة لي

واجهت نفس التحدي في تشغيل Flask + Docker + Kubernetes. أدت زيادة حدود وحدة المعالجة المركزية والذاكرة إلى حلها بالنسبة لي.

نفس الشيء حدث لنا. زيادة حدود الموارد حل المشكلة.

حدث هذا لي فجأة على macOS Catalina (غير معبأ).

ما ساعدني هو:

  1. تثبيت opensl:
brew install openssl
  1. تشغيل وإضافة هذا إلى ~/.zshrc :
export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH

المصدر: https://stackoverflow.com/a/58445755/5811984

أواجه تحديًا مشابهًا وسأكون ممتنًا إذا تمكن شخص ما من مساعدتي.
هذا ما كان لدي.

" root @ ubuntu-s-1vcpu-1gb-nyc1-01 : ~ # sudo systemctl status gunicorn.service ● gunicorn.service - برنامج gunicorn daemon تم تحميله: تم تحميله (/etc/systemd/system/gunicorn.service ؛ معطل ؛ تعيين البائع مسبقًا: مُمكّن) نشط: نشط (قيد التشغيل) منذ الاثنين 2020-02-24 07:48:04 بالتوقيت العالمي ؛ 44 دقيقة قبل PID الرئيسي: 4846 (gunicorn) المهام: 4 (الحد: 1151) CGroup: /system.slice/gunicorn.service ├ ─4846 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectenv / bin / pythoprojectenv / bin / gunicorn - ├─4868 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - └─4869 / home / bright / djangoprojectdir / djangoprothonv / home / bin / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - 24 فبراير 07:48:04 ubuntu-s-1vcpu-1gb-nyc1-01 systemd [1]: توقف برنامج gunicorn الخفي. فبراير 24 07:48:04 ubuntu-s-1vcpu -1 gb-nyc1-01 systemd [1 ]: بدأ البرنامج الخفي gunicorn. 24 فبراير 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] بدء تشغيل gunicorn 20.0.4 فبراير 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] الاستماع على: unix: / run / gunicorn .soc 24 فبراير 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] استخدام العامل: المزامنة فبراير 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4866] [INFO] عامل التشغيل مع رقم التعريف الشخصي: 4866 24 فبراير 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4868] [INFO] عامل التشغيل مع pid: 4868 فبراير 24 07 : 48: 05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4869] [INFO] عامل التشغيل مع رقم التعريف الشخصي: 4869 فبراير 24 08: 03:41 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: - - [24 / فبراير / 2020: 08: 03: 41 +0000] "GET / HTTP / 1.0" 400 26 "-" "Mozilla /5.0 (Wi lines 1-20 / 20 (END) "هل يمكن لأي شخص مساعدتي في إصلاح ذلك؟

BrightNana هل يمكنك محاولة إعطاء dmesg ومعرفة ما إذا كان لديك أي أخطاء gunicorn؟
يمكن أن يساعد dmesg | grep gunicorn تصفية الأخطاء الأخرى

أهلا،
لدي نفس الخطأ في debian 9 عندما أريد تقديم gunicorn كخدمة systemd. إذا بدأت تشغيله من CLI ، فإن gunicorn يعمل بدون أخطاء.

مقتطف من dmesg | grep gunicorn :

مقتطف من journalctl :
Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1054] [INFO] Booting worker with pid: 1054 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1057] [INFO] Booting worker with pid: 1057 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1060] [INFO] Booting worker with pid: 1060 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1064] [INFO] Booting worker with pid: 1064 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1067] [INFO] Booting worker with pid: 1067 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1070] [INFO] Booting worker with pid: 1070 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1073] [INFO] Booting worker with pid: 1073 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1076] [INFO] Booting worker with pid: 1076 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1079] [INFO] Booting worker with pid: 1079 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1082] [INFO] Booting worker with pid: 1082 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1085] [INFO] Booting worker with pid: 1085 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1088] [INFO] Booting worker with pid: 1088 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1091] [INFO] Booting worker with pid: 1091 Mär 12 07:01:09 build-server gunicorn[828]: [2020-03-12 07:01:09 +0100] [1094] [INFO] Booting worker with pid: 1094
مقتطف من systemctl status :
● api.service - API Server for BuildingChallenge served with Gunicorn Loaded: loaded (/etc/systemd/system/api.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2020-03-12 08:26:01 CET; 22min ago Main PID: 8150 (gunicorn) Tasks: 3 (limit: 4915) Memory: 37.7M (high: 100.0M max: 500.0M) CGroup: /system.slice/api.service ├─ 8150 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app ├─28936 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app └─28938 /usr/bin/python3 -Es /usr/bin/lsb_release -a Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28909] [INFO] Booting worker with pid: 28909 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28912] [INFO] Booting worker with pid: 28912 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28915] [INFO] Booting worker with pid: 28915 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28918] [INFO] Booting worker with pid: 28918 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28921] [INFO] Booting worker with pid: 28921 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28924] [INFO] Booting worker with pid: 28924 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28927] [INFO] Booting worker with pid: 28927 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28930] [INFO] Booting worker with pid: 28930 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28933] [INFO] Booting worker with pid: 28933 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28936] [INFO] Booting worker with pid: 28936

شكرا لمساعدتك.

لقد طرحت علاقات عامة قد تساعد في تصحيح هذه الأنواع من المواقف. يمكن لأي شخص إلقاء نظرة؟
https://github.com/benoitc/gunicorn/pull/2315

واجهت نفس المشكلة مع تطبيق Flask الذي يعمل داخل Docker. كان العمال يعيدون التشغيل بلا حدود بمعرف عملية متزايد.
image

كانت المشكلة تتعلق بالذاكرة بالنسبة لي ، عندما قمت بزيادة الذاكرة المسموح بها لـ Docker ، ظهر العمال بشكل فعال.
image

tilgovi ، لا أمانع إذا كنت ترغب في دمج التغييرات التي أجريتها في العلاقات العامة الخاصة بك منذ أن وصلت إلى هناك أولاً. سيغطي هذا قتل العمال عبر الإشارات.

mildebrandt سألقي نظرة ، شكرا!

أرى أيضًا هذا السلوك فجأة ، باستخدام Gunicorn (20.0.4) + Gevent (1.5.0) + Flask داخل حاوية Docker.

[  328.699160] gunicorn[5151]: segfault at 78 ip 00007fc1113c16be sp 00007ffce50452a0 error 4 in _greenlet.cpython-37m-x86_64-linux-gnu.so[7fc11138d000+3e000]

في حالتي ، كما ترى ، يحدث Segfault بواسطة gevent. الغريب في الأمر أن هذه الحاوية عملت بشكل جيد قبل 5 أيام ، ولم يتغير أي من الكود منذ ذلك الحين أي إصدارات من أي من المكتبات ، وكلها تم تعيينها على إصدارات محددة. لقد قمت بإزالة flask-mail كتبعية ، والتي ربما تكون قد غيرت بشكل طفيف إصدارات التبعيات الأخرى.

التحديث من gevent == 1.5.0 إلى gevent == 20.9.0 حل المشكلة بالنسبة لي.

ifiddes مشكلتك على الأرجح ليست ذات صلة. أنت ترى مشكلة توافق ABI بين الإصدارات القديمة من gevent مع أحدث إصدار greenlet. راجع https://github.com/python-greenlet/greenlet/issues/178

آه ، شكرًا jamadden. كان هذا المنشور كل ما يمكن أن أجده عند البحث عن التفريخ اللانهائي لعمال التمهيد ، لكن هذه المشكلة وتوقيت تلك المشكلة يناسب مشكلتي.

لقد واجهت خطأ مشابهًا في جهاز AWS جديد مع Ubuntu 20.04 Server وبالرمز نفسه الذي يعمل على الإنتاج.

تم تكوين الجهاز باستخدام Ansible مثل آلات الإنتاج الأخرى.

[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Current configuration:
  config: None
  bind: ['127.0.0.1:8000']
  backlog: 2048
  workers: 1
  worker_class: uvicorn.workers.UvicornWorker
  threads: 1
  worker_connections: 1000
  max_requests: 0
  max_requests_jitter: 0
  timeout: 30
  graceful_timeout: 30
  keepalive: 2
  limit_request_line: 4094
  limit_request_fields: 100
  limit_request_field_size: 8190
  reload: False
  reload_engine: auto
  reload_extra_files: []
  spew: False
  check_config: False
  preload_app: False
  sendfile: None
  reuse_port: False
  chdir: /var/www/realistico/app
  daemon: False
  raw_env: []
  pidfile: None
  worker_tmp_dir: None
  user: 1001
  group: 1001
  umask: 0
  initgroups: False
  tmp_upload_dir: None
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  forwarded_allow_ips: ['127.0.0.1']
  accesslog: /var/www/realistico/logs/gunicorn/access.log
  disable_redirect_access_to_syslog: False
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  errorlog: /var/www/realistico/logs/gunicorn/error.log
  loglevel: debug
  capture_output: False
  logger_class: gunicorn.glogging.Logger
  logconfig: None
  logconfig_dict: {}
  syslog_addr: udp://localhost:514
  syslog: False
  syslog_prefix: None
  syslog_facility: user
  enable_stdio_inheritance: False
  statsd_host: None
  dogstatsd_tags: 
  statsd_prefix: 
  proc_name: None
  default_proc_name: realistico.asgi:application
  pythonpath: None
  paste: None
  on_starting: <function OnStarting.on_starting at 0x7f7ba5fdd550>
  on_reload: <function OnReload.on_reload at 0x7f7ba5fdd670>
  when_ready: <function WhenReady.when_ready at 0x7f7ba5fdd790>
  pre_fork: <function Prefork.pre_fork at 0x7f7ba5fdd8b0>
  post_fork: <function Postfork.post_fork at 0x7f7ba5fdd9d0>
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f7ba5fddaf0>
  worker_int: <function WorkerInt.worker_int at 0x7f7ba5fddc10>
  worker_abort: <function WorkerAbort.worker_abort at 0x7f7ba5fddd30>
  pre_exec: <function PreExec.pre_exec at 0x7f7ba5fdde50>
  pre_request: <function PreRequest.pre_request at 0x7f7ba5fddf70>
  post_request: <function PostRequest.post_request at 0x7f7ba5f6e040>
  child_exit: <function ChildExit.child_exit at 0x7f7ba5f6e160>
  worker_exit: <function WorkerExit.worker_exit at 0x7f7ba5f6e280>
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f7ba5f6e3a0>
  on_exit: <function OnExit.on_exit at 0x7f7ba5f6e4c0>
  proxy_protocol: False
  proxy_allow_ips: ['127.0.0.1']
  keyfile: None
  certfile: None
  ssl_version: 2
  cert_reqs: 0
  ca_certs: None
  suppress_ragged_eofs: True
  do_handshake_on_connect: False
  ciphers: None
  raw_paste_global_conf: []
  strip_header_spaces: False
[2020-10-15 15:11:49 +0000] [18068] [INFO] Starting gunicorn 20.0.4
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Arbiter booted
[2020-10-15 15:11:49 +0000] [18068] [INFO] Listening at: unix:/run/gunicorn.sock (18068)
[2020-10-15 15:11:49 +0000] [18068] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-10-15 15:11:49 +0000] [18080] [INFO] Booting worker with pid: 18080
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] 1 workers
[2020-10-15 15:11:51 +0000] [18083] [INFO] Booting worker with pid: 18083
[2020-10-15 15:11:53 +0000] [18086] [INFO] Booting worker with pid: 18086
...
[2020-10-15 15:12:09 +0000] [18120] [INFO] Booting worker with pid: 18120
[2020-10-15 15:12:11 +0000] [18123] [INFO] Booting worker with pid: 18123

بعد ضياع الكثير من الوقت في محاولة حل هذه المشكلة دون نجاح (وبدون أي أخطاء في السجلات) ، جربت مع Hello world ووجدت هذا الخطأ:

ModuleNotFoundError: No module named 'httptools'

بعد تثبيت httptools ، يعمل تطبيق Hello world بشكل جيد ، وبشكل غير متوقع ، يعمل أيضًا تطبيقي.

ليس لدي أي فكرة عن سبب عدم تسجيل الخطأ أو سبب تثبيت هذه المكتبة على الأجهزة الأخرى ولكن ليس على الجهاز الجديد ، ولكن هذا حل المشكلة بالنسبة لي.

لو حدث هذا مؤخرًا وأزال عقدة kubernetes التي كانت تعمل من خلال استهلاك كل وحدة المعالجة المركزية. بفضل التلميح حول dmesg وجدت خطأ في النهاية:

[225027.348869] traps: python[44796] general protection ip:7f8bd8f8f8b0 sp:7ffc21a0b370 error:0 in libpython3.7m.so.1.0[7f8bd8dca000+2d9000]

في النهاية ، كانت مشكلتي نسخة أخرى من https://github.com/python-greenlet/greenlet/issues/178 وتم حلها عن طريق تحديث gunicorn و gevent و greenlet إلى أحدث إصدار.

نظرًا لأن هذه الأنواع من الاستثناءات لا تنشئ أي سجلات للغة بيثون ، ولا يمكن التقاطها ، وأرجع كود الخروج 0 ، ويمكن أن تعطل الجهاز عند حدوثها ، ومن الصعب جدًا إدارتها.

أقترح أن يكتشف الجونيكورن حدوث تحطم سريع من هذا النوع و

ربما max_consecutive_startup_crashes مع كون الإعداد الافتراضي هو num_workers * 10؟

دعنا نتتبع طلب ميزة حلقة التعطل في # 2504. لدينا أيضًا PR لتسجيل الدخول الإضافي # 2315. سأغلق هذه المشكلة لأنه يبدو أن الجميع قد نجح في تصحيح مشكلاتهم والآن لدينا بعض طلبات الميزات والتحسينات لمساعدة الآخرين في المستقبل. شكرا لكم جميعا!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات