نُشغّل مثيلاً مستضافاً ذاتياً من Discourse على https://discourse.bokeh.org منذ عدة سنوات. وبشكل عام، كان النظام متيناً للغاية ويتطلب جهداً ضئيلاً في الصيانة، وتحديداً، فإن إجراء التحديثات كان عادةً حدثاً غير ملحوظ يُنجز بنجاح تام ودون أي مشاكل.
ومع ذلك، اليوم، بعد التحديث إلى الإصدار 2.7beta7 (الذي بدا أنه اكتمل دون مشاكل)، انهار موقعنا تماماً. استمر الموقع في العمل بشكل متعثر لبعض الوقت مع صفحات لم تُعرض بشكل صحيح وأخطاء في وحدة تحكم JavaScript، لكن بعد محاولة التراجع، أصبح واجهة المستخدم غير وظيفية. عند تسجيل الدخول إلى الـ droplet، حاولت أيضاً دون جدوى ما يلي:
إعادة البناء
./launcher rebuild app
فشل هذا الإجراء بعدة طرق عبر عدة محاولات.
تشخيص Discourse
./discourse-doctor
الاستعادة
./launcher enter app
discourse restore <ملف النسخ الاحتياطي>
بعد ذلك، تمكّنت على الأقل من إتمام إعادة بناء ناجحة أدت إلى حالة “تثبيت جديد”، أي ظهور رسالة “تهانينا، لقد قمت بتثبيت Discourse!”
لذا، حاولت الآن تشغيل discourse restore مرة أخرى، لكن فشل مرة أخرى
استثناء: 1 من المنشورات لم يتم إعادة تعيينها إلى عنوان URL جديد لـ S3. فشل الترحيل إلى S3 لقاعدة البيانات 'default'.
/var/www/discourse/lib/file_store/to_s3_migration.rb:131:in `raise_or_log'
/var/www/discourse/lib/file_store/to_s3_migration.rb:86:in `migration_successful?'
/var/www/discourse/lib/file_store/to_s3_migration.rb:357:in `migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:65:in `migrate'
/var/www/discourse/lib/file_store/s3_store.rb:240:in `copy_from'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:62:in `restore_uploads'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:44:in `restore'
/var/www/discourse/lib/backup_restore/restorer.rb:62:in `run'
script/discourse:145:in `restore'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/thor-1.1.0/lib/thor/base.rb:485:in `start'
script/discourse:286:in `'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli/exec.rb:63:in `load'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli/exec.rb:63:in `kernel_load'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli/exec.rb:28:in `run'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli.rb:494:in `exec'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli.rb:30:in `dispatch'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/cli.rb:24:in `start'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/exe/bundle:49:in `block in '
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/lib/bundler/friendly_errors.rb:130:in `with_friendly_errors'
/usr/local/lib/ruby/gems/2.7.0/gems/bundler-2.2.7/exe/bundle:37:in `'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `'
جاري محاولة التراجع...
جاري التراجع...
جاري تنظيف الأشياء...
جاري إسقاط الدوال من مخطط discourse_functions...
جاري إزالة المجلد المؤقت '/var/www/discourse/tmp/restores/default/2021-04-23-235404'...
جاري وضع علامة على انتهاء الاستعادة...
جاري إشعار 'system' بنهاية الاستعادة...
انتهى!
[فشل]
المثير للدهشة هو أنه أثناء الاستعادة، بدا الموقع وكأنه يعود إلى طبيعته، حيث ظهرت المحتويات القديمة. ثم حدث الفشل، والآن لا يظهر شيء، وقد اختفت الحسابات، وما إلى ذلك.
أحتاج حقاً إلى أي توجيه أو اقتراحات هنا. لدينا نسخ احتياطية يومية تعود لأسبوع (أو أكثر في Glacier إذا لزم الأمر). قمنا بحذف فئة غير مستخدمة قبل بضعة أيام، هل يمكن أن يكون ذلك سبباً للمشاكل؟ سأحاول تجربة نسخة احتياطية أقدم لأرى، لكن أي إرشادات حول عملية استعادة لا يمكن اختراقها ستكون موضع ترحيب.
كإضافة جانبية، ألا يحتوي النسخ الاحتياطي على المنشورات التي تم استيرادها في الأصل من قائمة بريدية، لكنها كانت موجودة على موقع Discourse لسنوات؟؟ كان لدينا 24 ألف منشور، وليس 5 آلاف منشور قبل هذا.
حسناً، ربما يكون هناك منشور واحد تالف فقط؟ أعتقد أنك ستحتاج إلى استعادة قاعدة البيانات، إصلاحها، ثم إعادة بناء ملف النسخ الاحتياطي باستخدام قاعدة البيانات الجديدة. لكن من الصعب حقاً تحديد ذلك.
هل تتوفر لديك نسخة احتياطية حديثة من القطرة أو لقطة يمكنك استعادتها؟
للأسف، لا. نسخ احتياطية من DigitalOcean تكون أسبوعية فقط، وقد قمت بإعداد نسخ احتياطية يومية لمنصة Discourse إلى خدمة S3، مع الاحتفاظ بنسخ حديثة لمدة أسبوع ونسخ قديمة لمدة عام في خدمة Glacier. وبالنظر إلى تجربتي الإيجابية السابقة مع العديد من ترقيات Discourse، كنت أعتقد أن هذا الإجراء سيكون كافيًا وأفضل (وقد قمت سابقًا بإجراء عمليات استعادة اختبارية ناجحة).
حسنًا، في الواقع، تحديث. في نوبة من اليأس، قمت ببساطة بإنهاء سكريبت الاستعادة قسرًا أثناء خطوة
مزامنة الملفات مع S3
قبل أن يشكو من المنشور السيئ الوحيد ويبدأ في التراجع.
في الواقع، عاد الموقع للعمل وكان يمكن الوصول إليه في وضع الأمان. قمت بتعطيل مكون السمة “نسخ ولصق” لكتل الكود الذي يبدو أنه غير متوافق تمامًا الآن مع النسخة التجريبية الأحدث. بعد ذلك، يبدو أن الموقع يعمل بشكل صحيح إلى حد كبير حتى بدون وضع الأمان. ولكن:
هل هناك أي إجراءات مقترحة للتأكد من أن الأمور نظيفة قدر الإمكان؟ على سبيل المثال، إعادة رفع الأصول إلى S3 وإعادة “خبز” المحتوى؟ أين توجد أفضل وأحدث تعليمات لذلك؟
تعديل: насколько我能أستطيع أن أقول، كل شيء عاد إلى طبيعته. الصور في المنشورات القديمة يتم تحميلها بشكل صحيح من S3/CDN. إذن، يبدو أن سؤالي هو: إذا كنا نرفع الصور إلى S3، فهل يجب إلغاء تحديد هذا الخيار؟
تضمين الملفات المرفوعة في النسخ الاحتياطية المجدولة. سيؤدي تعطيل هذا إلى نسخ قاعدة البيانات فقط.
أعتقد أنني ظننت أن تحديد هذا الخيار يوفر طبقة إضافية من التكرار، لكن يبدو أنه مصدر كل هذه المشاكل أثناء الاستعادة؟
في المرة الأخيرة التي انتقلت فيها إلى موفر استضافة آخر، واجهتُ مشاكل أيضًا مع S3 عند الاستعادة. لذا سألتُ عنها وكانت الإجابة بنعم. عندما تخزّن صورك في S3، فيجب عليك إجراء النسخة الاحتياطية دون تضمين التحميلات. فقط قاعدة البيانات. لكنني لا أعرف ما إذا كانت هذه هي الحل في حالتك. إذا كنت ستجربها، فقم بإنشاء لقطة (snapshot) مسبقًا.
@pfaffman شكرًا لك! يبدو أن الموقع يعمل الآن بشكل طبيعي تمامًا، لكنني لن أرفض نظرة سريعة أو فحصًا للتأكد من صحته في حال توفرت لديك الفرصة، إذا كنت مستعدًا. وقد سجلت معلوماتك التجارية للتواصل التجاري لأي طوارئ مستقبلية بغض النظر.
إليك ملخصًا للحدث، في حال كان مفيدًا لأحد آخر
ملخص
بعد ترقية (ناجحة)، تسببت إضافة غير رسمية غير متوافقة في تلف واجهة المستخدم للموقع. لم يكن هذا معروفًا في ذلك الوقت، لذا تم بدء عملية استعادة النسخة الاحتياطية، لكنها واجهت مشاكل بسبب إعدادات لم تكن مثالية.
التفاصيل
تم بدء ترقية إلى 2.7beta7، واكتملت بنجاح.
ومع ذلك، بعد الترقية، تعرضت واجهة المستخدم للموقع لتلف شديد: اختفت نصوص المنشورات بالكامل، واختفت شريط التنقل العلوي (بما في ذلك قسم المستخدم/تسجيل الدخول)، وأبلغت وحدة تحكم JavaScript عن أخطاء.
اتضح أن السبب هو مكون غير متوافق من طرف ثالث مخصص لنسخ ولصق كتل الأكواد، لكن هذا لم يكن معروفًا في ذلك الوقت.
كما لم يكن معروفًا في ذلك الوقت إمكانية الدخول إلى وضع الأمان. لو كان ذلك معروفًا، لكان من الممكن تجنب المشاكل المتبقية.
تم الحصول على الوصول إلى \admin عبر التنقل المباشر، وتم بدء محاولة للتراجع. أدى ذلك فورًا إلى تسجيل خروج المستخدم، ولم يظهر أن هناك أي طريقة لتسجيل الدخول مرة أخرى مع واجهة المستخدم التالفة.
تم تسجيل الدخول إلى Digital Ocean Droplet لبدء استعادة يدوية باستخدام أحدث ملف نسخة احتياطية مضغوط (tarball) من S3.
فشلت العديد من محاولات الاستعادة في الخطوة الأخيرة تقريبًا، بعد رفع أصول S3، بسبب وجود خطأ في منشور واحد.
يبدو أن السبب هو أن عمليات الاستعادة التي تحاول إعادة رفع الأصول إلى S3 قد تكون غير مستقرة (هناك عدة تقارير عن ذلك على Meta).
ومع ذلك، لم يكن هناك حاجة لنسخ أصول التحميل احتياطيًا، لأنها مخزنة بالفعل على S3!
خلال إحدى محاولات الاستعادة العديدة، تم مسح الموقع أيضًا للبدء من “صفحة نظيفة”، لذا فإن عمليات التراجع بعد فشل الاستعادة أدت الآن إلى التراجع إلى موقع فارغ.
في النهاية، في مقامرة يائسة، قمت بتشغيل عملية الاستعادة، وقمت بإيقاف النص البرمجي قسريًا أثناء رفع S3 (قبل الفشل والتراجع مباشرة).
عاد الموقع إلى العمل، لكنه أظهر مشاكل واجهة المستخدم السابقة. ومع ذلك، كان وضع الأمان معروفًا وتم استخدامه، وعمل الموقع بشكل طبيعي مع تعطيل الإضافات والمظاهر.
تم إزالة جميع الإضافات والمظاهر غير الرسمية (بما في ذلك مكون “النسخ واللصق”)، وعمل الموقع بشكل طبيعي بعد ذلك.
تم التحقق من أن الصور التي تم تحميلها سابقًا لا تزال تعمل، وأن مصدرها هو شبكة CDN الخاصة بـ S3.
أعتقد أن خطوة الرفع النهائية و"إعادة الخبز" لم تكن ضرورية لأن الأصول كانت لا تزال موجودة على S3، ولم تكن هناك حاجة لتحديث المنشورات لاستخدام عناوين URL جديدة.
لست متأكدًا من أي خطوات استعادة متبقية تم تجاهلها بعد إيقاف النص البرمجي، لكن حتى الآن لم يواجه أي شخص أي مشاكل مع الموقع في حالته الحالية.
الدروس / الإجراءات
ابدأ دائمًا بوضع الأمان لتشخيص المشاكل في المستقبل.
قم بإيقاف الإعداد الذي يتضمن التحميلات في النسخ الاحتياطية (سأقترح على Discourse تحذير المستخدمين من هذا الموقف).
قم بإزالة جميع الإضافات ومكونات المظاهر غير الرسمية.
أقترح تفعيل ميزة نسخ كتل الأكواد المدمجة الجديدة.
قم بتفعيل نسخ Digital Ocean الأسبوعية للصور كإجراء احتياطي للتعافي.
لو كان لي أن أقترح اقتراحًا واحدًا فيما يتعلق بعملية الاستعادة، لكان ذلك هو تقديم بعض الخيارات لجعلها أكثر مرونة. على سبيل المثال، إذا كان العائق الوحيد أمام استعادة ناجحة هو منشور واحد تالف، فسأضغط على مفتاح Y بلا تردد إذا طُلب مني: «هل تريد حذف المنشور التالف؟»
سيتم تضمين ذلك في إحدى إصدارات 2.8 التجريبية القادمة. للأسف، لم يكن جاهزًا للإصدار القادم 2.7 بعد.
أعتذر عن عدم رؤيتي لطلبك للمساعدة في وقت سابق. إليك نصيحة للجميع الذين يواجهون صعوبة في استعادة النسخ الاحتياطية المخزنة على S3: قم باستخراج ملف dump.sql.gz من النسخة الاحتياطية وأعد تسمية الملف. على سبيل المثال، إذا كان اسم النسخة الاحتياطية الأصلي هو discourse-2020-10-09-133921-v20201007124955.tar.gz، فيجب أن يكون اسم الملف الناتج discourse-2020-10-09-133921-v20201007124955.sql.gz. يجب أن تعمل عملية استعادة هذا الملف.