حين تتوقّف حركة TCP للكاميرا الصناعيّة لعدّة ثوانٍ - كيف نضيق نطاق انتظار إعادة الإرسال باستخدام طوابع زمنيّة RFC1323

· · TCP, الشبكات, تصحيح الأخطاء, تطوير Windows, الكاميرا الصناعيّة

حين تتوقّف حركة TCP للكاميرا الصناعيّة لعدّة ثوانٍ - كيف نضيق نطاق انتظار إعادة الإرسال باستخدام طوابع زمنيّة RFC1323

في أنظمة الكاميرات الصناعيّة واتّصالات التحكّم بالمعدّات، غالباً ما تكون الأعطال الأشدّ إيلاماً هي تلك التي يكون فيها المتوسّط سريعاً ولكن تتوقّف أحياناً لعدّة ثوانٍ. معدّل إعادة الإنتاج منخفض، لذلك تبدو في الوقت نفسه واجهة المستخدم والـ threads و GC و SDK الكاميرا و NIC والـ switch جميعها مشبوهةً قليلاً.

الحالة هنا كانت توقّفاً نادراً لعدّة ثوانٍ في اتّصال TCP بين تطبيق المضيف وكاميرا صناعيّة. بعد التحقيق، لم يكن السبب الحقيقيّ توقّف التطبيق.
بل كان انتظار إعادة إرسال TCP بسبب فقد الحزم. وفي هذه البيئة، ساعد تفعيل خيار الطوابع الزمنيّة على نمط RFC1323 (المنظّم اليوم تحت RFC 7323) في تقليص ذلك الانتظار المرئيّ.

تمّ تعميم أسماء المنتجات والـ topology والأرقام الدقيقة هنا، لكنّ المنطق قابل لإعادة الاستخدام مباشرةً في العمل الحقيقيّ.

المحتويات

  1. النسخة المختصرة
  2. كيف بدا العَرَض
  3. ما الذي كان يحدث فعلاً
  4. ما الذي تحقّقنا منه في التحقيق
  5. لماذا ساعدت طوابع RFC1323 الزمنيّة
  6. ما الذي غيّرناه فعليّاً
  7. ما يجب فحصه في Wireshark
  8. دليل قواعد عامّة تقريبيّة
  9. الخلاصة
  10. المراجع

1. النسخة المختصرة

  • التوقّف النادر لعدّة ثوانٍ في اتّصال TCP قد يكون انتظار إعادة الإرسال بعد فقد الحزم، لا توقّف التطبيق
  • إذا أظهر التقاط الحزم Retransmission مع فجوات زمنيّة كبيرة، وتطابقت مدّة التوقّف مع شكل انتظار RTO، فهذا دليل قويّ
  • خيار طوابع TCP الزمنيّة موجود لقياس RTT و PAWS، كما يزيل غموض RTT حول الـ segments المُعاد إرسالها
  • في هذه الحالة، قلّل تفعيل الطوابع الزمنيّة على نمط RFC1323 الوقت الذي كان فيه تقدير RTO يبقى محافظاً أكثر من اللازم، فأصبحت التوقّفات المرئيّة لعدّة ثوانٍ أقصر بكثير
  • لكن هذا ليس سحراً يزيل فقد الحزم نفسه. ما زالت الروابط الفيزيائيّة و NICs والـ switches والأجهزة الوسيطة والبرامج الـ drivers وتصميم الـ buffering تحتاج إلى مراجعة منفصلة

باختصار، إذا كان السبب الحقيقيّ لـ “تتوقّف أحياناً لعدّة ثوانٍ” هو وقت يُقضى في الانتظار داخل TCP، فإنّ إعادة المحاولة على مستوى التطبيق وحدها تخطئ مركز المشكلة. عادةً ما يكون الأسرع هو النظر إلى الـ wire أوّلاً وتأكيد ما إذا كان التوقّف فعلاً انتظار إعادة إرسال.

2. كيف بدا العَرَض

2.1. التطبيق يبقى حيّاً، لكنّ الاستجابة فقط تتوقّف لعدّة ثوانٍ

كان أوّل جزء مربك هو أنّ التطبيق بأكمله لم يبدُ ميتاً.

  • لم تكن واجهة المستخدم متجمّدة تماماً
  • لم تتحطّم العمليّة
  • لم يكن استخدام CPU مثبّتاً
  • لكنّ الردود على أوامر التحكّم بالكاميرا اختفت أحياناً لعدّة ثوانٍ

هذا يجعل العَرَض صعب التمييز عن deadlock التطبيق أو الحلقات اللانهائيّة. في التحكّم بالمعدّات، حتّى توقّف واحد لعدّة ثوانٍ يُحسّ كأنّه إيقاف للخطّ، لذا فإنّ كون المتوسّط جيّداً لا يساعد كثيراً في الميدان.

2.2. لأنّه منخفض التردّد، فإنّ السجلّات وحدها تخفيه

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

عندما تعتمد على السجلّات فقط، تبدو الأمور غالباً هكذا:

  • يُظهر سجلّ التطبيق “أُرسل” ثمّ “لم يأتِ شيء بالمقابل”
  • يبدو الجانب المستقبِل وكأنّه “لم يصل شيء”
  • الأحداث غير المرتبطة التي تحدث في النافذة الزمنيّة نفسها تُشتّت اللوم

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

3. ما الذي كان يحدث فعلاً

3.1. أدّى فقد الحزم إلى انتظار إعادة الإرسال

كانت القصّة الأساسيّة بسيطة. فُقدت حزمة في مكان ما على المسار، انتظر المرسِل ACK، لم يصل أيّ شيء، فانتظر انتهاء RTO وأعاد الإرسال.

sequenceDiagram
    participant Host as Host app
    participant Net as Network
    participant Cam as Camera side

    Host->>Net: Control command (Seq=N)
    Note over Net: Packet is lost here
    Note over Host: Waiting for ACK
    Note over Host: Recovery of this request now includes RTO waiting
    Host->>Net: Retransmit control command
    Net->>Cam: Retransmitted packet arrives
    Cam-->>Net: ACK
    Net-->>Host: ACK
    Note over Host: Communication resumes here

من وجهة نظر التطبيق، بدا الأمر وكأنّ “التطبيق توقّف لعدّة ثوانٍ”. من وجهة نظر TCP، كان ببساطة “ما زال ينتظر لأنّ ACK لم يصل بعد”.

تبادلت قناة التحكّم هذه من نوع request / response رسائل صغيرة ولم يكن لديها كمّيّة كبيرة من البيانات غير المؤكّدة قيد النقل. لذا بدلاً من تجميع ما يكفي من duplicate ACKs لتحفيز fast retransmit، كان من الأسهل أن يصبح انتظار RTO هو المشكلة المرئيّة.

3.2. تطابقت التوقّفات متعدّدة الثواني مع شكل انتظار RTO

انتظار إعادة إرسال TCP محافظ. يضع RFC 6298 خطّ الأساس الأوّليّ لـ RTO عند ثانية واحدة، ويرفع النتائج الأصغر إلى ذلك الحدّ الأدنى، ويضاعف الانتظار بعد كلّ timeout.

flowchart LR
    A[Packet loss] --> B[No ACK arrives]
    B --> C[RTO waiting]
    C --> D[Retransmit]
    D --> E{Does an ACK arrive?}
    E -- yes --> F[Communication resumes]
    E -- no --> G[Double the RTO]
    G --> C

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

4. ما الذي تحقّقنا منه في التحقيق

4.1. أوّلاً أزل الأسباب داخل العمليّة

قبل اتّخاذ القرار بأنّ المشكلة في TCP، تمّ إزالة المشتبه بهم النموذجيّين داخل العمليّة أوّلاً.

ما تحقّقنا منه السبب الاستنتاج في هذه الحالة
UI thread / worker threads لاستبعاد deadlocks والانتظارات المتبادلة ليس السبب الرئيسيّ
استخدام CPU لاستبعاد التأخير الناتج عن الحمل العالي البحت لم يكن CPU مثبّتاً أثناء التوقّفات
GC / ضغط الذاكرة لاستبعاد توقّفات stop-the-world لم يلائم نمط التوقّف
استدعاءات SDK الكاميرا لاستبعاد الانتظار الداخليّ في SDK لم يطابق التأخير على مستوى الـ wire
التقاط الحزم لتأكيد إعادات الإرسال على الـ wire هنا أصبح السبب الحقيقيّ مرئيّاً

النقطة المهمّة هي عدم تحديد الجاني بناءً على الطوابع الزمنيّة لسجلّ التطبيق فقط. في تطبيقات التحكّم بالمعدّات، قد يكون انتظار الطبقة العليا مجرّد انعكاس لانتظار الطبقة السفلى.

4.2. أكّد إعادات الإرسال عبر التقاط الحزم

أظهر التقاط الحزم TCP Retransmission خلال نوافذ التوقّف، وقبل ذلك مباشرةً، لم يكن ACK المتوقّع قد عاد.

أمور مفيدة للفحص:

  • ما إذا كانت قيمة Seq نفسها يُعاد إرسالها
  • ما إذا كان التأخير قبل إعادة الإرسال يطابق التوقّف المرئيّ
  • ما إذا كان الشكل يبدو كانتهاء RTO وليس duplicate ACK / fast retransmit
  • ما إذا كان نفس tcp.stream متضمّناً في كلّ مرّة

بمجرّد أن تتطابق هذه الأمور، يصبح “التطبيق توقّف” أقلّ احتمالاً بكثير من “TCP كان ينتظر لإعادة الإرسال”.

4.3. افحص خيارات TCP المتفاوض عليها

الشيء التالي للفحص كان handshake لـ SYN / SYN-ACK. يتمّ التفاوض على الطوابع الزمنيّة أثناء three-way handshake، لذا إذا لم يكن TSopt موجوداً هناك، فإنّ ذلك الاتّصال لا يستخدمها.

sequenceDiagram
    participant Host as Host
    participant Cam as Camera side

    Host->>Cam: SYN + TSopt ?
    Cam-->>Host: SYN/ACK + TSopt ?
    Host->>Cam: ACK
    Note over Host,Cam: Only if negotiation succeeds here will TSopt appear later

هذه إحدى الحالات التي تكون فيها الحقيقة على الـ wire أهمّ من شاشة الإعدادات.

5. لماذا ساعدت طوابع RFC1323 الزمنيّة

في المشاريع الحقيقيّة، لا يزال الناس يقولون كثيراً “طوابع RFC1323 الزمنيّة”، رغم أنّ المنظّم الحاليّ هو RFC 7323. يحتفظ هذا المقال بالاسم المألوف، لكنّ الموضوع هو خيار طوابع TCP الزمنيّة نفسه.

5.1. الطوابع الزمنيّة موجودة من أجل RTTM و PAWS

خيار الطوابع الزمنيّة موجود بشكل رئيسيّ من أجل:

  • RTTM (Round-Trip Time Measurement)
  • PAWS (Protect Against Wrapped Sequences)

في هذه الحالة، كان الجزء ذو الصلة هو RTTM. يُعاد صدى TSval للمرسِل في ACKs عبر TSecr، ممّا يجعل قياس RTT أكثر دقّة.

5.2. تزيل غموض RTT أثناء إعادة الإرسال

بمجرّد حدوث إعادة الإرسال، تساعد الطوابع الزمنيّة في إزالة غموض “هل كان هذا ACK يقابل الإرسال الأصليّ أم المُعاد؟” هذا بالضبط نوع الغموض الذي تهتمّ به خوارزميّة Karn.

يقول RFC 6298 إنّ عيّنات RTT لا ينبغي أن تُؤخذ من segments مُعاد إرسالها لأنّ ACK غامض. مع الطوابع الزمنيّة، يمكن تقليل ذلك الغموض لأنّ TSecr المُعاد يحدّد أيّ TSval مُرسَل قد تمّ الإقرار به فعلاً.

sequenceDiagram
    participant Host as Sender
    participant Cam as Receiver

    Host->>Cam: Seq=N, TSval=1000
    Note over Host,Cam: This segment is lost
    Note over Host: Waiting because ACK does not come back
    Host->>Cam: Retransmit Seq=N, TSval=2000
    Cam-->>Host: ACK, TSecr=2000
    Note over Host: Now it can tell which transmission was acknowledged

كان هذا جوهر التحسين في هذه الحالة.

5.3. لماذا قلّلت الانتظار في هذه الحالة

هنا، حدث فقد الحزم أحياناً، وكلّ حدث جعل تقدير RTT / RTO يميل للبقاء محافظاً لفترة أطول من المثاليّ. مع تفعيل الطوابع الزمنيّة، أصبح من الأسهل تحديث تقدير RTT حتّى حول المواقف المتعلّقة بإعادة الإرسال، ممّا قلّل الوقت الذي ظلّ فيه RTO قديماً ومنتفخاً.

بعبارة أخرى، لم يكن التغيير “اجعل TCP سريعاً بشكل سحريّ”.
بل كان قلّل الوقت الذي يبقى فيه TCP منتظراً بحذر أكثر ممّا هو ضروريّ.

لا تزال هناك تحذيرات مهمّة:

  • يعتمد هذا جزئيّاً على تنفيذ TCP stack
  • الطوابع الزمنيّة وحدها لا تزيل فقد الحزم نفسه
  • إذا كانت الطبقة الفيزيائيّة أو الأجهزة الوسيطة سيّئة، فإنّ السبب الجذريّ في مكان آخر
  • لا تزال SACK و NIC drivers وإعدادات offload وسلوك الـ switch مهمّة بشكل منفصل

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

6. ما الذي غيّرناه فعليّاً

6.1. تفعيل الطوابع الزمنيّة

كان التغيير العمليّ هو التأكّد من أنّ كلا طرفي الاتّصال يستطيعان التفاوض على خيار الطوابع الزمنيّة. على Windows، يظهر هذا غالباً في الوثائق أو الإعدادات كجزء من مجموعة خيارات RFC 1323.

ومع ذلك، في الممارسة العمليّة، فإنّ “مفعَّل في إعداد” يهمّ أقلّ من “TSopt مرئيّ في SYN / SYN-ACK”.

6.2. تأكيد TSopt في SYN / SYN-ACK

بعد التفعيل، تمّ تأكيد هذه الأمور الثلاثة:

  • هل يحمل SYN للاتّصال المعنيّ TSopt؟
  • هل يُعيد SYN/ACK أيضاً TSopt؟
  • هل تستمرّ data segments و ACKs اللاحقة في حمل حقول الطوابع الزمنيّة؟

عندها فقط يمكنك القول بصدق “الطوابع الزمنيّة قيد الاستخدام فعلاً على هذا الاتّصال”.

6.3. أين تنظر إذا لم يساعد ذلك

إذا كانت الطوابع الزمنيّة مفعّلة لكنّ التوقّف لا يزال سيّئاً، فإنّ المشتبه بهم التاليين هم غالباً:

  • معدّل فقد الحزم الفعليّ لا يزال مرتفعاً
  • middlebox يجرّد أو يُتلف خيارات TCP
  • إعدادات NIC / driver / offload لديها مشكلة منفصلة
  • يعلّق تصميم التطبيق الكثير على request متزامن واحد بحيث يبدو انتظار واحد كأنّه توقّف كامل
  • السبب الحقيقيّ ليس TCP على الإطلاق بل توقّفات معالجة على جانب الكاميرا أو ضغط queue داخل الجهاز

ترتيب عمليّ هو:

  1. أوّلاً أكّد انتظار إعادة الإرسال على الـ wire
  2. ثمّ افحص ما إذا تمّ التفاوض على TSopt فعلاً
  3. ثمّ قارن السلوك قبل / بعد تفعيل الطوابع الزمنيّة
  4. إذا بقي، حقّق في مصدر الفقد وتصميم التطبيق بشكل منفصل

7. ما يجب فحصه في Wireshark

تشمل display filters المفيدة:

tcp.stream eq <target stream>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr

نصائح عمليّة:

  • ضيّق إلى الاتّصال ذي الصلة بـ tcp.stream
  • اعرض Time delta from previous displayed packet لتكون مدّة التوقّف مرئيّة مباشرةً
  • أكّد ما إذا كان Retransmission يظهر في اللحظة المعنيّة
  • أكّد التفاوض على TSopt في SYN / SYN-ACK
  • افحص ما إذا كانت ACKs تحمل TSecr

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

8. دليل قواعد عامّة تقريبيّة

العَرَض الشكّ الأوّل الإجراء الأوّل
توقّف نادر لعدّة ثوانٍ انتظار TCP RTO أكّد إعادات الإرسال والفجوات الزمنيّة في التقاط الحزم
يحدث التوقّف في نفس التوقيت تقريباً كلّ مرّة انتظار داخل العمليّة، معالجة على جانب الجهاز، timeout ثابت افحص الـ threads واستدعاءات SDK وسجلّات الجهاز
يسوء فقط تحت الحمل CPU، GC، queueing افحص CPU والمقاطعات والذاكرة وعمق الـ queue
تتدهور اتّصالات كثيرة دفعةً واحدة الطبقة الفيزيائيّة، الـ switch، الأجهزة الوسيطة افحص إحصائيّات NIC والكابلات والمنافذ وسجلّات البنية التحتيّة
تمّ تغيير الإعدادات لكن لا شيء تحسّن لم يتمّ التفاوض على الطوابع الزمنيّة فعلاً أعد فحص SYN / SYN-ACK

السطر الأخير يحدث كثيراً. الإعداد الذي تمّ تغييره والحقيقة على الـ wire ليسا الشيء نفسه.

9. الخلاصة

النقاط المهمّة في هذه الحالة:

  • “تتوقّف أحياناً لعدّة ثوانٍ” قد يكون انتظار إعادة إرسال TCP بدلاً من توقّف التطبيق
  • إذا تطابقت مدّة التوقّف مع انتظار RTO وكانت إعادات الإرسال مرئيّة، فهذا دليل قويّ جدّاً
  • خيار طوابع TCP الزمنيّة موجود من أجل RTTM و PAWS ويساعد في إزالة غموض RTT أثناء إعادة الإرسال
  • في هذه الحالة، قلّلت الطوابع الزمنيّة على نمط RFC1323 الفترة التي ظلّ فيها RTO محافظاً أكثر من اللازم

أساليب يجب تجنّبها:

  • تحديد الجاني بناءً على سجلّات التطبيق فقط
  • تغيير إعدادات OS دون فحص الحزم الفعليّة
  • افتراض أنّ الطوابع الزمنيّة ستزيل أيضاً سبب فقد الحزم

أساليب تعمل بشكل جيّد:

  • انظر إلى الـ wire أوّلاً
  • أكّد شكل انتظار إعادة الإرسال
  • أكّد التفاوض على TSopt
  • حتّى بعد ذلك، حقّق في مصدر الفقد وتصميم التطبيق بشكل منفصل

في هذا النوع من العيوب، “اجعله أسرع” ليس المهمّة الأولى.
المهمّة الأولى هي تحديد أين ينتظر النظام فعلاً.

10. المراجع

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

حين يتعطّل تطبيق التحكّم بكاميرا صناعيّة فجأةً بعد شهر (الجزء الأوّل) - كيفيّة العثور على handle leak وتصميم السجلّات للتشغيل طويل الأمد

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

صفحة دراسة حالة توضّح بنية مشابهة للتشخيص أو تحديد الأولويات أو إعادة التصميم.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

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

روابط عامة

العودة إلى المدونة