عندما تكلفك ثانية التوقف مليونًا
\n\nتخيل: أنت تُحدّث متجرًا إلكترونيًا يعمل بـ PHP، ترفع الإصدار الجديد عبر FTP، وفجأة يتوقف الموقع لمدة 5 دقائق. خمس دقائق تعني 300 ثانية. خلال هذا الوقت، يغادر 100 عميل محتمل إلى منافسيك، وتخسر ليس فقط المال بل أيضًا السمعة. هل هذا الألم مألوف لك؟
\n\nفي عالم اليوم، حيث لا يغفر المستخدمون الأخطاء، نشر PHP بدون توقف (Zero-Downtime Deployment) ليس ترفًا بل ضرورة حتمية. ولكن كيف تنفذ نشرًا سلسًا إذا كانت بيئتك تعتمد على PHP وNginx وخوادم متعددة؟ دعنا نتعرف على ذلك من خلال أمثلة واقعية.
\n\nلماذا PHP أصعب مما تبدو؟
\n\nعلى عكس Node.js أو Python، لا يدعم PHP تعدد المهام (Multithreading) بالمعنى التقليدي. كل طلب يُعالج بواسطة عملية PHP-FPM منفصلة. هذا يفرض قيودًا: لا يمكنك ببساطة "إعادة تحميل" الكود دون فقدان الجلسات الحالية. لكن هذه الخاصية نفسها تمنحنا قوة هائلة — القدرة على تحويل حركة المرور بسلاسة بين الإصدارات.
\n\nالمشاكل الرئيسية عند نشر PHP:
\n- \n
- قطع الاتصالات — يفقد المستخدم بيانات النموذج أو الجلسة \n
- التخزين المؤقت القذر — يعيد الكود القديم بيانات من ذاكرة تخزين مؤقت قديمة \n
- ترحيلات قاعدة البيانات المكسورة — الإصدار الجديد من قاعدة البيانات غير متوافق مع الكود القديم \n
لتجنب هذه المشاكل، نستخدم استراتيجيات مجربة. ونعم، النشر بدون توقف ليس سحرًا، بل خطة واضحة.
\n\nالاستراتيجية الأولى: النشر الأزرق-الأخضر (Blue-Green Deployment)
\n\nالطريقة الأكثر موثوقية هي الاحتفاظ بنسختين كاملتين من التطبيق: "الزرقاء" (الحالية) و"الخضراء" (الجديدة). يعمل Nginx كموازن أحمال.
\n\nكيف يبدو هذا عمليًا
\nلنفترض أن لديك خادمين: app1.example.com (أزرق) و app2.example.com (أخضر). كلاهما يشغل PHP-FPM. حاليًا، الخادم الأزرق نشط. تقوم بنشر الإصدار الجديد على الخادم الأخضر، وتختبره، ثم تحوّل Nginx إلى الخادم الأخضر.
مثال على إعدادات Nginx للتحويل:
\n\n# nginx.conf\nupstream php_backend {\n # في البداية، الخادم الأزرق نشط\n server app1.example.com:9000 weight=1; # أزرق\n server app2.example.com:9000 weight=0; # أخضر (معطل)\n}\n\nserver {\n listen 80;\n server_name myshop.com;\n\n location ~ \\.php$ {\n fastcgi_pass php_backend;\n include fastcgi_params;\n fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n }\n}\n\n\nبعد النشر على الخادم الأخضر، نغير الأوزان:
\n\n# بعد النشر — نوجه حركة المرور\nupstream php_backend {\n server app1.example.com:9000 weight=0; # أزرق (معطل)\n server app2.example.com:9000 weight=1; # أخضر (نشط)\n}\n\n\nنعيد تحميل Nginx دون توقف: nginx -s reload. جميع الاتصالات الحالية تُنهى بشكل صحيح، والجديدة تتجه إلى الخادم الأخضر. نشر PHP بدون توقف مضمون!
المزايا والعيوب
\nالمزايا: تحمل كامل للأعطال، يمكنك التراجع بسرعة (ببساطة أعد الأوزان).
\nالعيوب: تحتاج إلى ضعف الموارد (خوادم أو حاويات).
الاستراتيجية الثانية: التحديث التدريجي (Rolling Update)
\n\nإذا كانت ميزانيتك محدودة، استخدم التحديث التدريجي. الفكرة: نقوم بتحديث خوادم PHP واحدًا تلو الآخر، دون إيقاف الباقي. لا يلاحظ المستخدمون أي توقف، لأن Nginx يعيد توجيه الطلبات إلى الخوادم الحية.
\n\nالتنفيذ باستخدام PHP-FPM
\nلنفترض أن لديك 3 خوادم تعمل بـ PHP-FPM. نخرجها واحدًا تلو الآخر من التناوب، نحدّث الكود، ثم نعيدها.
\n\nالخطوة 1: إيقاف الخادم عن موازن الأحمال (Graceful Shutdown):
\n\n# على الخادم الذي نحدّثه\nsudo systemctl stop php8.1-fpm\n# سيتوقف Nginx تلقائيًا عن إرسال الطلبات إلى هذا الخادم لأنه غير متاح\n\n\nالخطوة 2: تحديث الكود (عبر git pull أو rsync أو Docker).
\n\nالخطوة 3: إعادة تشغيل PHP-FPM:
\n\nsudo