مشاكل API بين التطبيق والخادم: الإصدارات والأخطاء والتوافق مع النسخ القديمة
تنشر تحديثًا للخادم فتتعطل نسخ قديمة من التطبيق عند بعض العملاء، وكل فريق يقول إن تغييره سليم. هذا الدليل لمدير التقنية وصاحب المشروع: كيف تشخص السبب، وما الترتيب الذي يمنع تكراره مع كل تحديث.
أغلب مشاكل API في التطبيق بعد تحديث الخادم لها سبب واحد: الخادم يتحدث فورًا، وتطبيقات الجوال لا تتحدث فورًا. في أي لحظة يخدم خادمك عدة نسخ من التطبيق مثبتة على أجهزة عملائك، وأي تغيير كاسر (حذف حقل، أو تغيير نوعه، أو قيمة حالة جديدة لا تعرفها النسخة القديمة) يعطلها. العلاج ليس في التطبيق وحده: قاعدة «أضف ولا تغيّر» في الواجهات، وإصدارات API للتغييرات الكاسرة، ونموذج أخطاء موحد ومهلات مضبوطة، وحد أدنى مدعوم للتطبيق مع تحديث إجباري عند الحاجة، واختبارات عقد تكشف الكسر قبل النشر، ومراقبة للأخطاء بحسب نسخة التطبيق.
تنشر تحديثًا للخادم يوم الأحد، وفي المساء تصل شكاوى: تطبيق بعض العملاء ينهار عند فتح الطلبات، وآخرون يرون «حدث خطأ» في صفحة الدفع. فريق الخادم يقول إن التغيير صغير ومختبر، وفريق التطبيق يقول إن التطبيق لم يتغير. كلاهما صادق، والمشكلة في المسافة بينهما. هذا الدليل يساعدك على تشخيص ما يحدث، ثم على بناء ترتيب يمنع تكراره مع كل تحديث.
لماذا تنكسر النسخ القديمة من التطبيق تحديدًا؟
في موقع الويب، كل زائر يحصل على آخر نسخة لحظة تحديثها. في تطبيق الجوال الأمر مختلف: التحديث يمر بمراجعة المتجر، ثم يصل تدريجيًا، ثم يعتمد على قرار المستخدم أو إعداد التحديث التلقائي في جهازه. حتى الإطلاق المرحلي في App Store، بحسب مساعدة App Store Connect، يوزع التحديث على سبعة أيام لعينة من مستخدمي التحديث التلقائي، ومن أوقف التحديث التلقائي يبقى على نسخته حتى يحدّث بنفسه. والأجهزة الميدانية المُدارة قد لا تُحدَّث إلا حين تقرر إدارة الأجهزة ذلك.
- نسخة التطبيق 2.3ما زالت على أجهزة بعض العملاء
- نسخة التطبيق 2.4الشريحة الأكبر
- نسخة التطبيق 2.5تنتشر تدريجيًا
- تحديث الخادمنشر
لهذا لا يكفي أن يختبر فريق الخادم تغييره مع آخر نسخة من التطبيق. السؤال الصحيح قبل كل نشر: ما أقدم نسخة ما زالت تستخدم هذا الخادم، وهل ستعمل بعد التغيير؟
تشخيص مشاكل API في التطبيق: العَرَض والسبب والعلاج
ابدأ من العَرَض الذي يصفه العملاء أو تظهره تقارير الأعطال، واسأل دائمًا: هل يظهر في كل النسخ أم في نسخ محددة؟ الإجابة وحدها تفصل مشكلة التوافق عن غيرها.
| العَرَض | السبب المرجح | كيف تتأكد | العلاج |
|---|---|---|---|
| انهيار عند فتح شاشة في النسخ القديمة فقط | حقل حُذف أو أعيدت تسميته أو تغير نوعه، أو قيمة فارغة حيث لا يتوقعها التطبيق | قارن استجابة الواجهة قبل النشر وبعده، وسجل الانهيار بحسب نسخة التطبيق | أعد الحقل كما كان، وضع الشكل الجديد في إصدار جديد من الواجهة |
| انهيار أو شاشة فارغة بعد إضافة حالة جديدة للطلب | النسخة القديمة لا تعرف القيمة الجديدة ولا تتعامل مع المجهول | ابحث عن القيمة الجديدة في الاستجابات التي سبقت الأعطال | لا ترسل القيمة الجديدة للنسخ التي لا تعرفها، وعلّم التطبيق التعامل مع أي قيمة مجهولة |
| قائمة فارغة رغم وجود بيانات | تغير شكل الاستجابة: تغليف القائمة داخل حقل، أو تغيير الترقيم | قارن بنية الاستجابة لا حالتها؛ الخادم يرد بنجاح والتطبيق لا يجد ما يبحث عنه | تغيير البنية تغيير كاسر مكانه إصدار جديد |
| «حدث خطأ» عام في كل مكان | لا يوجد نموذج أخطاء موحد، فيعرض التطبيق رسالة عامة لكل رد غير متوقع | سجلات الخادم برموز الأخطاء ورسائلها لتلك الطلبات | نموذج أخطاء ثابت برموز يفهمها التطبيق |
| فشل الدخول في نسخ معينة | تغيير في طريقة المصادقة أو صلاحية الرموز أو شكلها | نسبة أخطاء المصادقة بحسب نسخة التطبيق | دعم الطريقتين خلال فترة انتقال |
| طلبات أو دفعات مكررة | التطبيق يعيد المحاولة بعد انتهاء المهلة، والخادم ينفذ الطلب مرتين | طلبان متطابقان بفارق ثوانٍ من المستخدم نفسه | مفتاح منع التكرار للعمليات المالية والحساسة |
| مؤشر تحميل لا ينتهي | لا مهلة في التطبيق، أو نقطة بطيئة في الخادم | زمن الاستجابة لتلك النقطة في مراقبة الخادم | مهلات في التطبيق، ومعالجة البطء في الخادم |
| أرقام أو أسعار خاطئة دون أي عطل ظاهر | تغيير في المعنى لا في الشكل: السعر أصبح شاملًا للضريبة، أو الوقت بتوقيت مختلف | راجع سجل التغييرات بحثًا عن تغيير في الحساب أو الوحدة | تغيير المعنى كاسر مثل تغيير الشكل، ويحتاج حقلًا جديدًا أو إصدارًا جديدًا |
الصف الأخير أخطر الصفوف، لأنه لا ينتج انهيارًا ولا رسالة خطأ. التطبيق القديم يعرض السعر الشامل ثم يضيف إليه الضريبة مرة أخرى، ولا ينتبه أحد حتى يشتكي عميل من فاتورة.
ما الذي يُعد تغييرًا كاسرًا في واجهة يستهلكها تطبيق جوال؟
الخلاف بين فريقي الخادم والتطبيق يبدأ غالبًا من هذا السؤال. اجعل الإجابة مكتوبة ومتفقًا عليها:
تغيير آمن للنسخ القديمة
- إضافة حقل جديد اختياري إلى الاستجابة
- إضافة نقطة (Endpoint) جديدة
- إضافة معامل اختياري للطلب له قيمة افتراضية تحافظ على السلوك القديم
- تحسين الأداء دون تغيير الشكل أو المعنى
- قيمة جديدة في قائمة ثابتة، فقط إن كانت كل النسخ تتعامل مع المجهول
تغيير كاسر يحتاج إصدارًا جديدًا
- حذف حقل أو إعادة تسميته أو تغيير نوعه
- جعل معامل اختياري إلزاميًا في الطلب
- تغيير شكل الاستجابة أو الترقيم أو الترتيب الافتراضي
- تغيير رموز الأخطاء أو معناها
- تغيير طريقة المصادقة
- تغيير معنى قيمة دون تغيير اسمها: وحدة، أو ضريبة، أو توقيت
القاعدة العملية: أضف ولا تغيّر. إن احتجت إلى تغيير حقل، فأضف حقلًا جديدًا بالشكل الجديد، واترك القديم يعمل حتى تختفي النسخ التي تقرؤه. وهذا ما تذكره صفحة تطوير واجهات الربط APIs: إضافة الحقول دون حذف أو إعادة تسمية، والتغييرات الكاسرة تذهب إلى إصدار جديد.
إدارة إصدارات API: ما يناسب تطبيقات الجوال
إدارة الإصدارات ليست رقمًا في الرابط فقط، بل سياسة تحدد متى يُنشأ إصدار جديد، وكم يبقى القديم، وكيف يُعرف من يستخدمه. ثلاث ممارسات تعمل معًا:
- رقم إصدار صريح للتغييرات الكاسرة: في المسار (مثل /v1 و/v2) أو في ترويسة الطلب. المسار أوضح في السجلات وأسهل في التوجيه؛ الترويسة أنظف في الروابط. المهم أن يرسل كل تطبيق الإصدار الذي بُني عليه، وأن يبقى الخادم قادرًا على خدمة الإصدارين.
- التطور داخل الإصدار بالإضافة فقط: لا يُنشأ إصدار جديد لكل حقل. داخل الإصدار الواحد يُسمح بالإضافات الآمنة وحدها، فتبقى الإصدارات قليلة وقابلة للصيانة.
- إعلان الإيقاف قبل حدوثه: حين يقترب إيقاف إصدار، يرسل الخادم إشارة مع استجاباته. توجد لذلك ترويسات قياسية: ترويسة Deprecation (RFC 9745) التي تعلن أن المورد متقادم أو سيتقادم، وترويسة Sunset (RFC 8594) التي تحدد متى سيتوقف عن الاستجابة. التطبيق الحديث يسجلها، وفريقك يعرف منها من ما زال على الإصدار القديم.
وقرار إيقاف إصدار قديم لا يُتخذ بالتاريخ وحده، بل بالبيانات: كم مستخدمًا ما زال على النسخ التي تستخدمه؟ ولا تتركه يعمل إلى الأبد أيضًا. قائمة OWASP لأمن واجهات API تصنف الإصدارات القديمة المتروكة دون صيانة ضمن مخاطر سوء إدارة جرد الواجهات، لأنها قد تعمل بمتطلبات أمنية أضعف وتتصل بقاعدة البيانات الحقيقية نفسها. واختيار نوع الواجهة نفسه يؤثر في هذه السياسة؛ مقالة REST أم GraphQL لواجهات التطبيق تقارن بينهما.
الحد الأدنى المدعوم والتحديث الإجباري
التوافق مع النسخ القديمة له حد. في لحظة ما يصبح دعم نسخة عمرها طويل أغلى من إجبار مستخدميها القلائل على التحديث، أو تكون هناك ثغرة أمنية لا يمكن تركها. هنا تحتاج إلى آلية مبنية في التطبيق من البداية:
- نقطة إعدادات يقرؤها التطبيق عند التشغيل: تعيد أدنى نسخة مدعومة وأدنى نسخة موصى بها. تحت الموصى بها يظهر تنبيه يمكن تجاوزه، وتحت المدعومة تظهر شاشة تحديث لا تُتجاوز.
- أدوات المتجر حين تتوفر: في Android توفر التحديثات داخل التطبيق من Google Play مسار «التحديث الفوري» بملء الشاشة للتحديثات الحرجة. وفي iOS تُبنى الشاشة داخل التطبيق وتوجه المستخدم إلى صفحة التطبيق في المتجر.
- توقيت إنساني: لا تقاطع مستخدمًا في منتصف الدفع أو الحجز. اعرض الشاشة عند الفتح أو بعد إتمام العملية الجارية.
التحديث الإجباري ليس بديلًا عن التوافق. إن كان كل تحديث للخادم يحتاج إجبار الجميع على التحديث، فالمشكلة في تصميم الواجهة لا في المستخدمين. ويجب أن تكون الآلية نفسها في التطبيق قبل أن تحتاجها؛ النسخة التي لا تحتوي عليها لا يمكن إجبارها لاحقًا. مقالة إجبار المستخدمين على تحديث التطبيق تفصل هذه الآلية.
عقد الواجهة واختبارات التوافق: اكتشف الكسر قبل النشر
أغلب التغييرات الكاسرة ليست مقصودة. مطور يعيد تسمية حقل لتحسين الكود، ولا يعرف أن نسخة قديمة من التطبيق تقرؤه. ما يمنع ذلك هو عقد مكتوب يُختبر آليًا:
- توثيق الواجهة بمعيار OpenAPI: كل نقطة ومدخلاتها ومخرجاتها وأخطاؤها. التوثيق يُولَّد من الكود أو يُختبر معه، فلا ينفصل عن الواقع.
- مقارنة العقد في كل تعديل: أدوات مقارنة مواصفات OpenAPI تكشف حذف الحقول وتغيير الأنواع قبل دمج الكود، فيتحول الكسر من شكوى عميل إلى تنبيه في خط البناء.
- اختبارات بطلبات النسخ القديمة: احفظ طلبات حقيقية تمثل كل نسخة مدعومة من التطبيق وما تتوقعه من ردود، وشغّلها على الخادم الجديد قبل النشر.
- بيئة اختبار بالنسخ القديمة مثبتة: جهاز أو أكثر عليه أقدم نسخة مدعومة، يمر عليها المسار الأساسي بعد كل نشر لبيئة الاختبار.
- نموذج أخطاء موحد: شكل واحد لكل رد خطأ، برمز يفهمه التطبيق ورسالة يمكن عرضها. معيار Problem Details (RFC 9457) يعرّف صيغة قياسية لتفاصيل الأخطاء في واجهات HTTP يمكن البناء عليها.
ولتسليم هذا التوثيق بمستوى يسمح لأي فريق لاحق بالعمل عليه، راجع مقالة توثيق واجهات API: ما الذي تطلبه من المطور.
المراقبة: اعرف أي نسخة تتعطل قبل أن يخبرك العميل
لا يمكنك تشخيص مشكلة توافق إن كانت سجلاتك لا تعرف نسخة التطبيق التي أرسلت الطلب. هذه الإضافات الصغيرة تغير طريقة عمل فريقك:
- كل طلب من التطبيق يحمل نسخة التطبيق والمنصة وإصدار الواجهة في ترويسة ثابتة، وتُسجَّل في الخادم.
- لوحة لمعدل الأخطاء وزمن الاستجابة لكل نقطة، مقسمة بحسب نسخة التطبيق.
- تنبيه بعد كل نشر للخادم إن ارتفعت الأخطاء لنسخة معينة، مع إمكانية الرجوع السريع.
- تقارير الأعطال في التطبيق موسومة بالنسخة، ومربوطة بالطلب الذي سبق الانهيار إن أمكن.
- تقرير دوري بتوزيع المستخدمين على النسخ وإصدارات الواجهة، لقرارات الحد الأدنى والإيقاف.
بهذه البيانات يتحول سؤال «هل التحديث كسر شيئًا؟» من انتظار الشكاوى إلى رقم يظهر في الساعة الأولى بعد النشر.
أخطاء شائعة في إدارة واجهات التطبيق والخادم
- اختبار الخادم مع آخر نسخة فقط: النسخة التي لم يعد يستخدمها الفريق ما زالت على أجهزة كثيرين.
- التطبيق يثق بالخادم ثقة كاملة: لا يتعامل مع حقل مفقود أو قيمة مجهولة أو رد متأخر، فينهار بدل أن يتجاوز.
- إصدار جديد للواجهة مع كل تحديث: تتراكم الإصدارات حتى يصبح الخادم خمسة خوادم في كود واحد.
- إيقاف إصدار قديم بالتاريخ لا بالبيانات: يتوقف التطبيق عند شريحة لم يعرف أحد حجمها.
- إعادة المحاولة دون حماية من التكرار: ضعف الشبكة يتحول إلى طلبات ودفعات مكررة.
- فريق الخادم وفريق التطبيق بلا عقد مشترك: كل فريق يعرّف «التغيير البسيط» بطريقته.
ما تطلبه من فريق التطوير أو المزود
- سياسة إصدارات مكتوبة: ما التغيير الكاسر، ومتى يُنشأ إصدار جديد، وكم يبقى القديم، وكيف يُعلن الإيقاف.
- توثيق OpenAPI محدث لكل نقطة، مع مقارنة آلية للعقد في خط البناء.
- قائمة بنسخ التطبيق المدعومة، واختبارات توافق تمثل أقدمها، تُشغل قبل كل نشر للخادم.
- نموذج أخطاء موحد، ومهلات وإعادة محاولة مضبوطة في التطبيق، ومفاتيح منع التكرار في العمليات المالية.
- آلية الحد الأدنى المدعوم والتحديث الإجباري في التطبيق، وإثبات أنها تعمل.
- لوحة مراقبة للأخطاء بحسب نسخة التطبيق، وتنبيه بعد النشر، وخطة رجوع.
- سجل تغييرات لكل نشر للخادم يذكر أثره على النسخ الحالية.
هذه الممارسات جزء مما نبنيه في واجهات الربط: توثيق OpenAPI قبل التنفيذ وبعده، ونموذج أخطاء موحد، ومفاتيح منع التكرار ومهلات وإعادة محاولة، وأرقام إصدارات مع فترة انتقال قبل إيقاف القديم وسجل تغييرات، ولوحات مراقبة لزمن الاستجابة والأخطاء. وفي تطوير Backend للتطبيقات تُبنى الخوادم بمراقبة وتنبيهات ودليل تشغيل. وإن كانت المشكلة قائمة الآن، فهي تبدأ في إصلاح أخطاء التطبيق بالتشخيص قبل الإصلاح، وترتيب الأخطاء حسب أثرها، واختبار يمنع عودة كل خطأ، ومراقبة للأعطال بعد الإصلاح.
ما تجهزه قبل التواصل
- متى بدأت المشكلة، وما الذي نُشر على الخادم قبلها، وسجل التغييرات إن وجد.
- نسخ التطبيق المتأثرة والمنصات، ولقطات أو خطوات تكرار الخطأ.
- تقارير الأعطال من أداة المراقبة في التطبيق، وسجلات الخادم للفترة نفسها.
- توثيق الواجهات الحالي، ولو كان ناقصًا أو قديمًا.
- توزيع المستخدمين على نسخ التطبيق من Play Console وApp Store Connect.
- هل يحتوي التطبيق الحالي على آلية تحديث إجباري، ومن يملك قرار تفعيلها.
الخلاصة: الخادم يلتزم بعقد مع كل نسخة ما زالت تعمل
مشاكل API بين التطبيق والخادم ليست سوء حظ مع كل تحديث، بل نتيجة غياب عقد واضح بين طرفين يتحدثان بسرعتين مختلفتين. اجعل التغييرات إضافية داخل الإصدار الواحد، وضع الكاسر في إصدار جديد بفترة انتقال معلنة، وعلّم التطبيق أن يتسامح مع المجهول، وابنِ آلية الحد الأدنى المدعوم قبل أن تحتاجها، واختبر كل نشر مع أقدم نسخة مدعومة، وراقب الأخطاء بحسب النسخة.
إن كانت نسخ تطبيقك القديمة تتعطل بعد تحديثات الخادم، أرسل وصف المشكلة وتفاصيل التطبيق عبر طلب تطوير تطبيق قائم، ونرد بخطة تشخيص أولية لواجهاتك ونسخ التطبيق المتأثرة.
أسئلة شائعة
لأن الإجبار يقاطع المستخدمين ويخسرك بعضهم، ولا يعمل إلا في النسخ التي بُنيت فيها آلية التحديث الإجباري أصلًا. الأصل أن يبقى الخادم متوافقًا مع النسخ المدعومة، وأن يُستخدم الإجبار للحالات الحرجة أو لإنهاء دعم نسخة قديمة جدًا.
لا يوجد رقم ثابت. القرار يُبنى على توزيع المستخدمين على النسخ من Play Console وApp Store Connect وسجلات الخادم، وعلى تكلفة إبقاء التوافق. حدد أدنى نسخة مدعومة، وراجعها دوريًا، وأعلن الإيقاف مسبقًا قبل رفعها.
آمنة غالبًا إن كان الحقل اختياريًا وكان التطبيق يتجاهل الحقول التي لا يعرفها. الاستثناء قيمة جديدة في قائمة ثابتة كحالات الطلب، فقد تعطل نسخة قديمة لا تتعامل مع القيمة المجهولة. اختبرها مع أقدم نسخة مدعومة قبل النشر.
الطريقتان صحيحتان. الرابط أوضح في السجلات وأسهل في التوجيه والتخزين المؤقت، والترويسة تبقي الروابط ثابتة. الأهم أن يرسل كل تطبيق الإصدار الذي بُني عليه، وأن تكون هناك سياسة مكتوبة لمتى يُنشأ إصدار جديد وكم يبقى القديم.
سجّل نسخة التطبيق والمنصة مع كل طلب، وراقب معدل الأخطاء لكل نقطة بحسب النسخة، وفعّل تنبيهًا بعد كل نشر. واختبر قبل النشر بطلبات محفوظة تمثل أقدم نسخة مدعومة، أو بجهاز عليه تلك النسخة في بيئة الاختبار.
خدمات وصفحات مرتبطة
نسخ تطبيقك القديمة تتعطل بعد تحديث الخادم؟
أرسل وصف المشكلة وتفاصيل تطبيقك، ونرد بخطة تشخيص أولية لواجهاتك ونسخ التطبيق المتأثرة، وما يمنع تكرارها مع كل تحديث.