لا أكتب هذا كمراجعة سلبية لـ REGXA، ولا أحاول أن أخبر أحدًا إن كان ينبغي له شراء VPS منها أم لا. هذه ببساطة واحدة من أيام عملي كمطور.
نقلت حمل عمل عاديًا إلى خادم KVM افتراضي بموارد 2 vCPU و2 GB من RAM و60 GB من NVMe. كان Nginx يعمل، وكان الـ backend يعمل، لكن الخادم تصرف كما لو أنه مثقل بشدة: تراكمت الطلبات، وأصبحت عمليات TLS بطيئة، وظلت الاتصالات مفتوحة، ووصلت بعض الطلبات في النهاية إلى أكثر من دقيقتين قبل أن تعود بحالة HTTP 504.
محاسبة CPU غيّرت اتجاه التحقيق
كان افتراضي الأول واضحًا: هناك شيء داخل الـ VPS يستهلك المعالج. ثم شغلت mpstat.
Average CPU steal: 92.58%
CPU 0 steal: 90.62%
CPU 1 steal: 94.57%
CPU user: 4.02%
CPU system: 1.47%
CPU iowait: 0.41%
CPU idle: 0.53%
أظهرت العينات الفردية مرارًا steal يتراوح تقريبًا بين 89 و98%. كما كان ضغط CPU شديدًا:
CPU PSI some avg10: 79.47
CPU PSI some avg60: 75.32
CPU PSI some avg300: 76.31
Load average: 5.85 / 5.75 / 5.73
كان هذا خادمًا باثنين فقط من vCPU. كان لدى Linux عمليات جاهزة للتنفيذ تنتظر CPU، لكن الرقم الأهم لم يكن استهلاك التطبيق المعتاد للمعالج، بل %steal.
استخدام CPU المرتفع وCPU steal مشكلتان مختلفتان
لو كان تطبيقي يستهلك المعالج فعلًا، لتوقعت قيمًا مرتفعة في user أو system. لكن صورة الخادم كانت تقريبًا كالتالي:
user: 4%
system: 1%
steal: 93%
CPU steal هو الوقت الذي تكون فيه وحدة المعالجة الافتراضية جاهزة للعمل لكن الـ hypervisor لا يقوم بجدولتها. لذلك عندما أقول إن وقت CPU كان يُنتزع من الـ VPS، فأنا أستخدم المعنى التقني الخاص بالافتراضية. لا أستطيع إثبات أن REGXA أعادت عمدًا تخصيص أنوية مادية كانت مخصصة حصريًا لي، ولا يمكن استنتاج النية من مقاييس الضيف. ما أستطيع إثباته هو أن النظام الضيف كان لديه عمل جاهز بشكل متكرر لكنه لم يحصل على وقت الجدولة المطلوب.
أزلت كل حركة المرور الإنتاجية
ظل هناك اعتراض منطقي: ربما كان حملي نفسه هو سبب المشكلة. لذلك أزلت هذا المتغير. نقلت الحمل النشط إلى مكان آخر، وأوقفت حركة المرور الإنتاجية إلى هذا الـ VPS، وانتظرت حتى فرغت الطوابير، ثم كررت القياس.
Average CPU steal: 94.17%
CPU 0 steal: 95.56%
CPU 1 steal: 92.83%
CPU user: 1.95%
CPU system: 0.59%
CPU iowait: 0.59%
CPU idle: 2.18%
أصبحت النتيجة أسوأ. ظلت عينات vmstat الفردية تعرض 91–98% steal، ووصل عدد العمليات الجاهزة التي تنتظر CPU إلى 15. وكان أهم تركيب للأرقام هو:
user: 1.95%
system: 0.59%
steal: 94.17%
كانت تطبيقاتي تكاد لا تفعل شيئًا، ومع ذلك ظل الجهاز الافتراضي يفقد معظم وقت الجدولة. لم يعد الحمل الإنتاجي الطبيعي تفسيرًا مقنعًا.
حتى localhost أصبح بطيئًا بصورة غير منطقية
اختبرت HTTPS عبر 127.0.0.1، وبذلك استبعدت DNS العام ومزود الإنترنت والمسافة الجغرافية ومسار الشبكة الخارجي.
مع وجود الحركة الإنتاجية، فشلت أربع من عشر محاولات HTTPS محلية أثناء TLS handshake. واستغرقت الطلبات الناجحة 29.30 و22.77 و12.25 و11.87 و11.12 و9.40 ثانية. بعض عمليات TLS handshake وحدها استغرقت نحو تسع ثوانٍ.
بعد إزالة الحركة الإنتاجية تحسن localhost، لكنه بقي غير مستقر: 0.061 و0.745 و0.830 و0.873 و1.010 و1.117 و1.121 و2.188 و3.355 ثانية. العملية المحلية نفسها قد تستغرق نحو 61 ms في محاولة وأكثر من 3.3 ثانية في المحاولة التالية.
بقية المنظومة أظهرت النتائج التابعة للمشكلة
في إحدى اللحظات لاحظت نحو 450 اتصالًا قائمًا، و122 اتصالًا orphaned، و110 اتصالات FIN-WAIT-1، و33 اتصالًا CLOSE-WAIT. وصل listen queue للـ backend المحلي إلى نحو 14–15، بينما وصل طابور HTTPS إلى نحو 40.
سجل Nginx استجابات HTTP 504 بعد 142.857 و138.902 و135.064 و129.819 و128.657 ثانية. وظلت طلبات أخرى مفتوحة نحو 67–130 ثانية. كما رأيت secure-connect timeouts في حدود 35–41 ثانية، وانقطاعات شبكة لقاعدة البيانات، وتأخيرات في TLS.
من السهل أن تبدو هذه كأنها مشكلات منفصلة في Nginx أو قاعدة البيانات أو الشبكة أو الـ backend. لكن زيادة المهلات لا تخلق وقت CPU لا يقوم الـ hypervisor بجدولته.
RAM والقرص لم يفسرا المشكلة
كان لا يزال متاحًا نحو 1.0–1.1 GiB من RAM، مع استخدام شبه معدوم للـ swap، ومن دون OOM events أو نشاط لـ OOM killer. كان نظام الملفات ممتلئًا بنسبة تقارب 20% فقط، مع نحو 44 GB متاحة. وظل I/O wait أقل من 1% أثناء قياسات CPU المهمة.
لم تكن الذاكرة قد نفدت، ولم يكن القرص ممتلئًا، ولم تكن تطبيقاتي تستهلك CPU المفقود. ظل المؤشر المسيطر هو %steal.
خادم KVM سليم بدا مختلفًا تمامًا
شغلت النوع نفسه من التشخيصات على VPS آخر بتقنية KVM كان يخدم حركة مرور طبيعية فعلًا:
Average CPU steal: 0.02%
CPU idle: 87.86%
CPU PSI avg10: 0.29
CPU PSI avg60: 0.63
CPU PSI avg300: 0.49
Load average: 0.47 / 0.33 / 0.14
أكملت طلباته العشرة المحلية عبر HTTPS في نحو 37–69 ms. وفي قياس لاحق لخادم إنتاجي آخر كان مشغولًا فعلًا، رأيت 61.71% user CPU و5.08% system CPU و24.09% idle، مقابل 0.13% steal فقط.
هذا هو الفرق الذي أهتم به الآن. قد يكون VPS مشغولًا لأن برامجي تستخدم المعالج بالفعل. وهذا يختلف تمامًا عن جهاز ضيف يقضي أكثر من 90% من وقت CPU المقاس في انتظار الـ hypervisor.
REGXA أكدت في النهاية وجود تنازع على البنية التحتية
من داخل الـ VM كنت أستطيع قياس ما يراه النظام الضيف، لكن لم أكن أستطيع رؤية الخادم المادي أو إعدادات الجدولة أو حصص CPU أو الأجهزة الافتراضية المجاورة. REGXA كانت تستطيع ذلك.
أخبرني الدعم في النهاية أن الـ VPS مستضاف على shared CPU infrastructure، وأن موارد CPU مشتركة بين عدة أجهزة افتراضية، وأن الأداء يمكن أن يتغير بحسب حمل العقدة المادية. كما قالوا إن بنية Frankfurt كانت تشهد طلبًا مرتفعًا بشكل خاص، ونسبوا صراحة ارتفاع CPU steal لدي إلى resource contention on the underlying infrastructure.
وأضافوا أنهم لا يستطيعون تعديل CPU quotas أو سياسات الجدولة أو تخصيص موارد CPU إضافية لهذا الـ VPS المشترك على البنية الحالية. وكان الحل التقني المقترح هو نقل الخادم إلى موقع أقل استخدامًا.
كان من الصعب بالنسبة لي التوفيق بين ذلك وبين اللغة التي رأيتها حول dedicated CPU cores وguaranteed resources. لا أستطيع رؤية الإعداد الدقيق للمضيف، ولذلك لا يمكنني تحديد ما إذا كانت الآلية المباشرة هي CPU overcommitment أو quotas أو scheduler weighting أو throttling أو مزيجًا منها. كما لا أستطيع إثبات النية. ولا أحتاج إلى ذلك: Linux أظهر 92–94% steal بصورة مستمرة، وREGXA نفسها نسبت الارتفاع إلى التنازع في بنيتها المشتركة.
استرداد المال احتاج جولة أخرى من الإصرار
بعد أن أصبحت مشكلة البنية التحتية واضحة، لم أرد الاستمرار في نقل الخادم واختبار عقد أخرى. أردت إلغاء الخدمة واستعادة أموالي.
في البداية عُرض علي مبلغ جزئي فقط، وكان الاسترداد المقترح إلى رصيد حساب REGXA بدلًا من البطاقة التي دفعت بها. بالنسبة لي، رصيد لدى المزود ليس معادلًا لاسترداد مالي عندما أحاول مغادرة الخدمة.
لذلك واصلت الرد وطلبت إعادة 100% من المبلغ إلى وسيلة الدفع الأصلية. في النهاية وافقت REGXA وأعادت كامل المبلغ إلى وسيلة الدفع الأصلية، ووصفت الاسترداد الكامل بأنه استثناء.
أقدّر أنهم أعادوا المبلغ كله في النهاية. لكن اضطراري إلى مواصلة الضغط من أجل الحل المالي بعدما كان الدعم قد أقر أصلًا بتنازع الموارد هو أيضًا جزء من تجربتي.
الدرس الذي بقي معي
أسهل خطأ كان أن أستمر في تحسين التطبيق. كان بإمكاني تغيير إعدادات Nginx، وزيادة المهلات، وتقليل التوازي، وإضافة retries، والتحقيق في MongoDB أو إعادة كتابة كود الـ backend. ربما كان بعض ذلك سيغيّر الأعراض، لكنه لن يجيب عن السؤال المهم: لماذا تجاوز CPU steal نسبة 90%؟
لم أعد أكتفي بالتأكد من أن SSH يعمل، وأن Nginx يبدأ، وأن health endpoint يعيد 200. في أي VPS جديد أنظر أيضًا إلى %user و%system و%iowait و%idle و%steal وCPU PSI وrun queue وزمن localhost.
وعندما يبدو شيء مريبًا، أزيل الحمل وأقيس مرة أخرى. في هذه الحالة أعطاني ذلك أوضح نتيجة في الحادث كله:
CPU user: 1.95%
CPU system: 0.59%
CPU steal: 94.17%
أنا لا أدعي أن كل خوادم REGXA VPS تتصرف بهذه الطريقة. اختبرت VPS واحدًا ووثقت ما حدث له. لكن الأدلة في هذا الخادم كانت واضحة بصورة غير معتادة: تطبيقاتي كانت بالكاد تستهلك CPU، بينما كان Linux يسجل أن الغالبية العظمى من وقت CPU الافتراضي تضيع في انتظار جدولة الـ hypervisor. ولاحقًا نسبت REGXA السلوك نفسه إلى تنازع الموارد في بنيتها المشتركة.
لهذا أوثق التجربة. ليست درجة تقييم ولا توصية، بل مجرد يوم آخر من أيامي كمطور — ومقياس لن أتجاهله مرة أخرى على أي VPS.