العودة إلى المدونة
31 أغسطس 2026Sergei Solod10 دقائق قراءة

كان خادم VPS متصلاً، ثم بدأ Linux ينتظر 18 ثانية لقراءة القرص

قصة عيبٍ حقيقي في بيئة إنتاج على Linux: ظل VPS متصلاً بينما كاد العمل الفعلي أن يتوقف. اقترب ضغط I/O من 100%، ووصلت بعض عمليات القراءة إلى 18.7 ثانية، وتعطلت عمليات EXT4 وNginx، بينما كان الـbackend نفسه يرد خلال نحو 3 مللي ثانية.

لينكسDevOpsخوادم VPSالأداءالتصحيح

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

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

في أسوأ الحالات سجلت:

CPU iowait:       97–100%
I/O PSI full:     ~95–98%
read latency:     up to 18.7 seconds
flush latency:    up to 53.6 seconds
I/O queue depth:  128+

كان Nginx يعمل، والـbackend يعمل، والآلة الافتراضية متصلة، لكن العمل المفيد كان شبه متوقف.

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

الحالة active (running) لم تعد تعني الكثير

بدأت بالفحوص المعتادة:

top
free -h
df -h
systemctl status nginx

وفي الفترات السليمة كنت أرى تقريباً:

D-state processes: 0
CPU iowait:        ~0%
disk latency:      ~2–4 ms
I/O PSI some:      0.04
I/O PSI full:      0.04

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

عينة iostat التي غيرت اتجاه التحقيق

r_await = 18744 ms
f_await = 53561 ms
aqu-sz  = 128.54
util    ≈ 100%
read    = 88 KB/s

كانت عمليات القراءة المكتملة تستغرق نحو 18.7 ثانية، وعمليات flush نحو 53.6 ثانية، ومتوسط الطابور تجاوز 128، بينما كان معدل القراءة المفيد فقط 88 KB/s.

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

توقفت عن التعامل مع iowait كتشخيص بحد ذاته

blocked processes: 4–9
CPU iowait:        97–100%
CPU idle:          0%

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

PSI أظهر أن I/O كان يوقف العمل الفعلي

cat /proc/pressure/io

في إحدى الفترات الشديدة:

some avg10=99.14
full avg10=95.55

وفي تجارب لاحقة اقترب full من 98%. في ضغط I/O، يعبر some عن الوقت الذي يكون فيه جزء من العمل غير الخامل متوقفاً بسبب I/O، بينما يعبر full عن الوقت الذي تتوقف فيه كل المهام غير الخاملة في الوقت نفسه. عندما تقترب القيمة من 100% فالأمر أكبر بكثير من مجرد «القرص مشغول»؛ عبء العمل بالكاد يحصل على فرصة للتقدم.

D-state جعلني أتوقف عن لوم عملية واحدة

ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'

وجود عملية واحدة لفترة قصيرة في D-state لا يثبت مشكلة تخزين. المهم كان أي العمليات تتوقف معاً. رأيت مكونات غير مرتبطة مثل jbd2 وsystemd-journald وعمليات Nginx وعمليات cache التابعة له وأنشطة أخرى لنظام الملفات.

إذا توقف الـbackend وحده أفحص الـbackend. وإذا توقف Nginx وحده أفحص Nginx. لكن عندما يتوقف Nginx وسجل النظام وخيط journal الخاص بـEXT4 معاً، يصبح العامل المشترك أهم من أي عملية منفردة. في حالتي كان ذلك العامل هو نظام الملفات ومسار التخزين تحته.

مكدسات النواة أوصلتني إلى الطبقة التالية

ظهر خيط journal الخاص بـEXT4 في مسارات مثل:

wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transaction

أما عمال Nginx فظهروا في مسارات قراءة ملفات عادية:

folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64

وفي لحظة ما سجلت النواة:

INFO: task nginx blocked for more than 122 seconds.

كان systemctl status nginx لا يزال يعرض active (running). المعلومتان صحيحتان: العملية موجودة، لكن إحدى مهام Nginx أمضت أكثر من دقيقتين عاجزة عن إكمال عمل مفيد. وجود عملية تعمل لا يعني أن الخدمة سليمة.

أنظف تجربة لدي استغرقت نحو ثلاثة مللي ثانية

فشل الطلب عبر Nginx:

HTTP=000
SSL connection timeout

ثم تجاوزت Nginx واتصلت بالـbackend المحلي مباشرة:

connect = 0.000423 s
TTFB    = 0.003063 s
total   = 0.003139 s

نحو 3 مللي ثانية. لم تكن حالة HTTP الدقيقة مهمة لهذا الاختبار. الـbackend قبل الاتصال ونفذ الطلب وأعاد الاستجابة فوراً تقريباً، بينما كانت عمليات Nginx تظهر في مسارات قراءة EXT4 في الوقت نفسه تقريباً.

application execution       → progressing normally
filesystem-backed web path  → not progressing normally

كلما تعمقت في الفحص أصبحت فرضية أن السبب داخل التطبيق أقل إقناعاً.

كان VPS نفسه قادراً على الانهيار خلال نحو 30 ثانية

قبل إحدى عمليات إعادة الإنتاج:

HTTP:          200
D-state:       0
CPU iowait:    3%
r_await:       ~1.18 ms
I/O PSI full:  ~2.95%

وبعد نحو نصف دقيقة:

D-state:       4
CPU iowait:    91%
CPU idle:      0%
I/O PSI some:  86.11%
I/O PSI full:  78.02%
r_await:       236.50 ms
HTTP:          000

ثم ساء أكثر:

CPU iowait:    96–100%
I/O PSI full:  ~98%
HTTPS queue:   512
HTTP:          000

وعندما أزلت الحمل كان من الممكن أن يحدث الانتقال العكسي سريعاً:

D-state:      0
CPU iowait:   6%
r_await:      ~0.98 ms
queue depth:  ~0.07
HTTP:         200

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

قيمة latency تساوي صفراً قد تكون عديمة الفائدة بشكل مفاجئ

رأيت أيضاً فترة في iostat فيها r_await = 0 بينما كان النظام واضحاً أنه غير سليم: iowait مرتفع، وعمليات في D-state، وI/O معلق، وقراءات مكتملة قليلة جداً، وتدفق شبه معدوم.

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

منذ ذلك الحين لم أعد أقرأ مقياس تخزين واحداً بمعزل عن غيره. أنظر إلى latency وIOPS وthroughput وqueue depth وI/O الجاري وD-state وPSI وإتمام الطلبات معاً.

حادثة واحدة تحولت إلى تحقيق دعم أطول بكثير

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

تكررت المشكلة في عدة أيام. وفي إحدى الحوادث أصبح VPS غير متاح لاحقاً لمدة 4 ساعات و41 دقيقة و15 ثانية وفق سجلات الخدمة لدي. لا أستطيع إثبات أن تعطل التخزين نفسه هو الذي أدخل الـVM في تلك الحالة؛ إثبات ذلك يحتاج إلى معلومات من المضيف لم تكن متاحة لي.

application
    ↓
Linux VFS
    ↓
EXT4
    ↓
virtual block device
    ↓
?

خلف علامة الاستفهام قد توجد طبقات virtualization وطوابير المضيف وشبكات التخزين والتخزين الموزع والوسائط الفعلية والمجدولات وأنظمة أخرى لا تراها الآلة الضيفة. كنت أرى أين يظهر العطل، لكنني لم أكن أرى السبب الفيزيائي النهائي.

صعّد FDCServers المشكلة داخلياً ونقل VPS في النهاية إلى عقدة أخرى. بعد النقل سجلت مرة أخرى تعطل تخزين شديداً من داخل الضيف. هذا لا يثبت أن كل عقد FDCServers لديها مشكلة تخزين؛ بل يثبت فقط أن المشكلة التي أصابت VPS الخاص بي لم تكن قد اختفت من وجهة نظري.

لماذا لا أعتبر هذه قصة سلبية عن FDCServers

من السهل تحويل حادثة بنية تحتية إلى حكم على مزود كامل. لا أريد فعل ذلك هنا.

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

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

طلبت من FDCServers إلغاء الخدمة وإعادة المبلغ. وقد أعادوا المال. وهذا جزء مهم من انطباعي العام.

لم أعد اختبار بنيتهم الحالية، لذلك لا أستطيع القول كيف يعمل VPS لديهم اليوم. كما لا أملك دليلاً على أن ما حدث لخادمي يمثل كامل بنيتهم. البنية التحتية تتغير باستمرار، ولا أريد تحويل حادثة صعبة في VPS واحد إلى حكم دائم على شركة كاملة. كما أنني لا أوصي بـFDCServers هنا. أنا فقط أوثق ما حدث لي.

أكثر ما استمتعت به كان Linux نفسه

التوقف كان محبطاً، لكن التحقيق كان ممتعاً. استمتعت فعلاً بالوصول إلى حدود المشكلة.

لم تكن لدي رؤية كافية لمعرفة السبب الفيزيائي النهائي. السؤال الذي أردت الإجابة عنه كان أبسط: أين يتوقف العمل المفيد؟

كان الـbackend يرد في نحو ثلاثة مللي ثانية. Nginx يقول إنه active، بينما كانت مكدسات النواة تظهره منتظراً داخل قراءات EXT4. أظهر vmstat عمليات محجوبة وI/O wait شديداً. أظهر PSI أن stalls الخاصة بـI/O تستهلك تقريباً كامل وقت العمل. أظهر iostat latency وطوابير ضخمة، وأظهر D-state عمليات غير مرتبطة تنتظر معاً. حتى النواة سجلت مهمة Nginx عالقة لأكثر من 122 ثانية.

لم يحل مقياس واحد الحادثة. توافق المقاييس هو ما فعل ذلك. وهذا أحد أسباب حبي لـLinux: يمكنك البدء بجملة غامضة مثل «موقعي لا يفتح أحياناً» ثم تحويلها تدريجياً إلى وصف دقيق للطبقة التي توقف عندها التقدم المفيد.

مسار التشخيص الذي أستخدمه الآن

top
free -h
df -h

date -u
uptime
cat /proc/pressure/io
cat /proc/pressure/memory
cat /proc/pressure/cpu
vmstat 1 10
iostat -x 1 10
ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'
ss -lntp
journalctl -k --since "30 min ago" --no-pager

وأحاول، عندما يكون ذلك ممكناً، اختبار كل جزء من مسار الطلب بشكل مستقل:

public request
      ↓
reverse proxy
      ↓
direct backend
      ↓
filesystem
      ↓
block device

بدلاً من سؤال «لماذا الخادم بطيء؟» فقط، أسأل الآن: في أي طبقة يتوقف العمل المفيد عن الاكتمال؟ هذا السؤال ينتج تجارب أفضل بكثير.

قاعدة أخيرة: اجمع الأدلة قبل إعادة التشغيل

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

Before reboot:
D-state:     high
I/O PSI:     ~97%
iowait:      ~100%
queues:      large
requests:    failing

After reboot:
D-state:     0
latency:     milliseconds
requests:    healthy

عندما تسمح حالة الخدمة وتأثيرها التجاري، أسجل أولاً وقت UTC وPSI وvmstat وiostat وD-state وwchan ورسائل النواة وطوابير sockets وأزمنة الطلبات. ثم أستعيد الخدمة، لا العكس.

الخادم كان يعمل، لكن عبء العمل لم يكن كذلك

لم أعرف أبداً أي مكوّن في المضيف تسبب نهائياً في الحادثة. لا أستطيع القول إن SSD محدداً تعطل، ولا تحديد عقدة تخزين بعينها، ولا إثبات ما حدث خلف جهاز الكتل الافتراضي.

لكن ما استطعت إثباته من داخل Linux كان كافياً:

read latency:       up to 18.7 s
flush latency:      up to 53.6 s
I/O PSI full:       almost 100%
iowait:             almost 100%
I/O queue:          128+
Nginx:              blocked in filesystem reads
EXT4/jbd2:          blocked waiting for I/O
direct backend:     ~3 ms
HTTP through Nginx: timing out

كان ذلك كافياً لفصل التطبيق عن الطبقة المتعثرة واتخاذ قرار تشغيلي. أعاد FDCServers قيمة الـVPS، وانتقلت إلى مكان آخر، ولا أتعامل مع حادثة بنية تحتية واحدة وصعبة كحكم على المزود.

ما بقي معي أهم: قد تكون العملية running، والخدمة active، والـVM online، والـping يعمل، ومع ذلك قد لا تنجز الآلة تقريباً أي عمل مفيد.

Linux يعطيك ما يكفي من الأدلة لتمييز هذه الحالات. عليك فقط أن تسأل النظام الأسئلة الصحيحة بينما العطل ما زال موجوداً.