حل بديل لصفحة الصيانة - هل يمكن فعل ذلك؟

أستخدم بناء الحاويات المزدوجة خلف CDN Cloudflare. يقلل بناء الحاويات المزدوجة من وقت التوقف، وكلا منتديي الإنتاج الرئيسيين لديهما حد أقصى 30 ثانية فقط من التوقف أثناء عمليات إعادة البناء. أحب وجود صفحة صيانة لأن صفحة “الويب غير متصل” الافتراضية قبيحة ولا تقدم أي فكرة عن المدة التي سيكون فيها الموقع غير متصل.

على سبيل المثال، لموقع على your-domain.com، أستخدم ببساطة مسار عامل Cloudflare مضبوطاً على *yourdomain.com/*.

الخطوة 1: إنشاء صفحة العامل

يمكنك إعداد صفحة الصيانة في صفحة إعدادات workers & pages على Cloudflare - انقر على زر create application:

ثم استخدم قالب hello world:

ثم أعطه اسماً وانقر على deploy:

ثم انتقل إلى صفحة نظرة عامة لتلك صفحة الصيانة وانقر على edit code:

والصق هذا الكود في نافذة الكود worker.js (استبدل نطاقك وأي رسالة تريدها، عدّل النص، لون النص، الخلفية، إلخ):

export default {
  async fetch(request, env, ctx) {
    try {
      // Fetch the original request from your server
      const response = await fetch(request);

      // If YOUR SITE is swapping containers, it throws a 502, 521, or 530
      if (response.status === 502 || response.status === 521 || response.status === 530) {
        return returnCustomErrorPage();
      }

      // If everything is fine, return the normal forum traffic
      return response;
    } catch (e) {
      // If the server is completely unreachable
      return returnCustomErrorPage();
    }
  }
};

function returnCustomErrorPage() {
  const html = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>System Refresh - YOUR-SITE.com</title>
      <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: center; padding: 50px; color: #333; background-color: #f9f9f9; }
        h1 { font-size: 2.5em; margin-bottom: 0.5em; color: #9400D3; }
        p { font-size: 1.2em; line-height: 1.5; }
        .container { max-width: 600px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
      </style>
    </head>
    <body>
      <div class="container">
        <h1>Just a quick update window</h1>
        <p><strong>YOUR-SITE</strong> is undergoing a brief 30-second system refresh.</p>
        <p>Grab a quick sip of your drink—this page will automatically refresh as soon as we are back online.</p>
      </div>
      <script>
        // Automatically check if the site is back up every 10 seconds
        setInterval(function() {
          window.location.reload();
        }, 10000);
      </script>
    </body>
    </html>
  `;

  return new Response(html, {
    status: 503, // 503 is best for SEO so Google doesn't penalize you for downtime
    headers: {
      "Content-Type": "text/html;charset=UTF-8",
      "Retry-After": "30"
    }
  });
}

يجب أن يبدو شيئاً ما مثل هذا. انقر على deploy لحفظه:

الخطوة 2: إضافة المسار

الآن انتقل إلى صفحة مسارات عامل Cloudflare وانقر على زر add route لإظهار نافذة المسار الجديد، املأ مسار النطاق واختر صفحة العامل التي أنشأتها للتو، ثم انقر على حفظ:

الخطوة 3: تشغيل التحديثات أو إعادة البناء

الآن، عندما تقوم بتسجيل الدخول إلى خادمك عبر ssh وتشغيل تحديثات النظام أو تقوم بإعادة البناء، بدلاً من ظهور صفحة “الموقع غير متصل” أو صفحة خطأ، ستظهر هذه الصفحة عندما يحدث التوقف فعلياً (أستخدم 30 ثانية في موقعي لأن هذا هو الحد الأقصى لمواقع)

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

أعتقد أن هذا هو كل شيء.

اختياري: تشغيل التحديثات باستخدام نص برمجي وجدولة

أستخدم أيضاً نص برمجي shell Unix على خادمي لتشغيل تحديث الحاويات المزدوجة المحدد، والذي أنشأته على النحو التالي:

cat << 'EOF' > /root/update-web.sh
#!/bin/bash
cd /var/discourse
echo "➡️ Pulling latest Discourse docker scripts..."
git pull

echo "➡️ Bootstrapping new web container in the background (takes ~8 mins)..."
./launcher bootstrap web_only

if [ $? -eq 0 ]; then
    echo "✅ Bootstrap successful! Swapping containers..."
    ./launcher destroy web_only && ./launcher start web_only
    echo "🚀 Done! Site updated with almost zero downtime."
else
    echo "❌ Bootstrap failed! Aborting swap to keep current site online."
fi
EOF

chmod +x /root/update-web.sh

ثم أقوم بتشغيله في موجه root على خادمي باستخدام الأمر ./update-web.sh.

يمكنك أتمتته لوقت محدد، مثل الساعة 1 صباحاً يوم الأحد بتوقيتك المحلي. بالنسبة لي، 1:00 صباحاً محلياً هو 8:00 صباحاً بتوقيت UTC، (يمكنك معرفة التاريخ UTC لخادمك) عن طريق كتابة date في موجه الأوامر عند تسجيل الدخول عبر ssh.

لذلك:

قم بتشغيل هذا الأمر لفتح جدول مهام خادمك:

crontab -e

(إذا طلب منك اختيار محرر، اضغط على المحرر المفضل لديك، 1 لـ nano هو الأرجح الأسهل)

أنتقل إلى أسفل التعليقات وألصق هذا:

0 8 * * 0 /root/update-web.sh >> /var/log/discourse-update.log 2>&1

(وهو ما يعني تشغيل ملف /root/update-web.sh في الدقيقة 0، الساعة 8 (بتوقيت UTC)، كل صباح أحد)

ثم احفظ واخرج (إذا كنت تستخدم nano):

  1. Ctrl + O للحفظ.
  2. Enter للتأكيد.
  3. Ctrl + X للخروج.

ثم يمكنني تشغيل cat /var/log/discourse-update.log عندما أستيقظ في صباحات أيام الأحد للتحقق مما إذا كان قد تم تشغيله بشكل صحيح. إذا استخدمت جدول مهام cron، فستريد ترك مسار صفحة العامل.

أعتقد أن هذا هو كل شيء. أخبرني إذا كان لديك أي أسئلة ههه. إنه أبسط بكثير مما جعلته يبدو عليه ههه. :grin: