404 Not Found

404 Not Found


nginx

نشر المشروع والإطلاق — من التطوير إلى الإنتاج

إطلاق المنتج مثل إطلاق صاروخ — الدروس الـ 24 الأولى تغطي التصميم والتصنيع، وهذا الدرس عن العد التنازلي والإطلاق. هناك قائمة مراجعة طويلة قبل الإطلاق، ولا يمكنك إشعال المحركات حتى يتم التحقق من كل بند. الإطلاق بدون قائمة مراجعة هو مقامرة.

1. ما ستتعلمه


2. القصة الحقيقية لـ Alice

(1) نقطة الألم: حوادث متكررة أثناء النشر

واجه PriceTracker مشاكل خلال أول عملية نشرين: في المرة الأولى، نسوا إعداد HTTPS؛ في المرة الثانية، تسبب قفل جدول خلال ترحيل قاعدة البيانات في انقطاع خدمة لمدة 10 دقائق؛ وفي المرة الثالثة، لم تكن السجلات مجمعة، لذا بعد ظهور مشكلة، قضى Charlie ساعتين في البحث في السجلات عبر خمسة خوادم. تحتاج Alice إلى عملية نشر منهجية لضمان أن كل نشر آمن وخاضع للرقابة.

(2) حل قائمة مراجعة النشر

النشر ليس مجرد "دفع الكود والانتهاء"؛ إنه سلسلة من قوائم المراجعة: التصلب الأمني، والتحقق من الأداء، واستراتيجية الترحيل، والنشر المرحلي، والتحقق من المراقبة — لا يمكنك الانتقال إلى الخطوة التالية إلا بعد التحقق من كل بند.

(3) العائد

النشر الثالث: تم التحقق من جميع بنود قائمة المراجعة؛ تم إعداد HTTPS؛ اكتمل الترحيل بدون توقف؛ بدأ إصدار متدرج بتوجيه 10% من حركة المرور للتحقق أولاً؛ والسجلات جُمعت تلقائيًا إلى Loki — عملية النشر بالكامل سارت بسلاسة، ولوحة مراقبة Charlie ظلت باللون الأخضر طوال الوقت.


3. قائمة مراجعة بيئة الإنتاج

(1) عملية الإطلاق

100%
flowchart TD
    A[تجميد الكود] --> B[تدقيق أمني]
    B --> C[اختبار حمل]
    C --> D[نشر Staging]
    D --> E[اختبار دخان]
    E --> F[إصدار كناري 10%]
    F --> G{المقاييس جيدة؟}
    G -->|نعم| H[نشر كامل 100%]
    G -->|لا| I[تراجع]
    I --> J[تحقيق]
    J --> A
    H --> K[مراقبة ساعة]
    K --> L[✓ مباشر]

(2) قائمة المراجعة ثلاثية الأبعاد

البُعد بند الفحص الحالة
الأمان إعداد شهادة HTTPS
CORS يسمح فقط بنطاقات الإنتاج
تفعيل تحديد المعدل
تم تغيير JWT SECRET_KEY
لا مفاتيح مُصلبة برمجيًا
اجتاز الفحص الأمني
الأداء Uvicorn Workers ≥ 4
حجم مناسب لتجمع اتصالات قاعدة البيانات
تفعيل تخزين Redis المؤقت
تفعيل ضغط GZip
اجتاز اختبار الحمل (QPS المستهدف)
المراقبة نقطة النهاية /health تعمل بشكل طبيعي
جمع مقاييس Prometheus
لوحة Grafana جاهزة
إعداد قواعد التنبيه
تجميع السجلات يعمل

4. استراتيجية النشر المرحلي

(1) النشر الأزرق-الأخضر

100%
flowchart LR
    LB[موازن التحميل] -->|100% حركة المرور| Blue[الأزرق v1]
    
    subgraph Deploy
        Green[الأخضر v2]
    end
    
    LB -.->|تبديل| Green
    
    style Blue fill:#4caf50
    style Green fill:#2196f3
الخطوة الإجراء التراجع
1 نشر بيئة الأخضر (v2) -
2 تشغيل اختبارات دخان في الأخضر -
3 LB يتحول إلى الأخضر العودة إلى الأزرق
4 مراقبة الأخضر لمدة 30 دقيقة العودة إلى الأزرق
5 تأكيد الاستقرار، إيقاف الأزرق -

(1) ▶مثال: إعداد Nginx للنشر الأزرق-الأخضر

NGINX
# nginx/conf.d/pricetracker.conf
upstream pricetracker_blue {
    server api-blue:8000;
}

upstream pricetracker_green {
    server api-green:8000;
}

# يخدم حاليًا الأزرق
server {
    listen 80;
    server_name api.pricetracker.example.com;

    location / {
        proxy_pass http://pricetracker_blue;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# التبديل إلى الأخضر بتغيير هدف proxy_pass
# ثم: docker compose -f docker-compose.green.yml up -d

الناتج:

TEXT
// التنفيذ ناجح

(2) الإصدار الكناري

الاستراتيجية توزيع الحركة فترة المراقبة التراجع
10% 1 v2 + 9 v1 15 دقيقة العودة إلى v1
30% 3 v2 + 7 v1 15 دقيقة العودة إلى v1
50% 5 v2 + 5 v1 15 دقيقة العودة إلى v1
100% الكل v2 30 دقيقة التراجع لإصدار الصورة

5. ترحيل قاعدة البيانات بدون توقف

(1) مبادئ الترحيل الآمن

المبدأ الوصف مثال
أضف فقط، لا تحذف أضف عمودًا جديدًا أولاً؛ لا تحذف العمود القديم ALTER TABLE ADD COLUMN new_col
توافق الكتابة المزدوجة الكود الجديد والقديم يعملان الكود الجديد يكتب في عمودين؛ الكود القديم يقرأ العمود القديم فقط
تنظيف مؤجل احذف الأعمدة القديمة فقط بعد تأكيد الاستقرار احذف الأعمدة القديمة بعد 7 أيام من نشر v2
ترحيل تزايدي غيّر شيئًا واحدًا فقط في كل مرة لا تضف أعمدة أو تغيّر أنواع بيانات في ترحيل واحد

(1) ▶مثال: ترحيل إضافة عمود آمن

PYTHON
# alembic/versions/xxx_add_wholesale_price.py
"""إضافة عمود wholesale_price إلى المنتجات

ترحيل آمن: ADD COLUMN غير حظر في PostgreSQL
"""

def upgrade():
    op.add_column(
        "products",
        sa.Column("wholesale_price", sa.Float(), nullable=True),
    )
    # تعيين القيمة الافتراضية للصفوف الموجودة (بيان منفصل للأداء)
    op.execute("UPDATE products SET wholesale_price = base_price * 0.6 WHERE wholesale_price IS NULL")
    # اجعلها غير قابلة للفراغ في الترحيل التالي بعد نشر الكود

def downgrade():
    op.drop_column("products", "wholesale_price")

الناتج:

TEXT
# تم تعريف الدالة بنجاح

(2) ترحيل محفوف بالمخاطر مقابل ترحيل آمن

نوع الترحيل الأمان خطر قفل الجدول التوصيات
ADD COLUMN آمن لا يوجد يمكن تنفيذه عبر الإنترنت
CREATE INDEX آمن نسبيًا ممكن استخدم CREATE INDEX CONCURRENTLY
DROP COLUMN خطر نعم تأكد أولاً أن الكود لم يعد يستخدمه
ALTER COLUMN TYPE خطر عالٍ ترحيل مرحلي (أضف عمود جديد ← رحّل البيانات ← احذف العمود القديم)
RENAME COLUMN خطر متوسط أعِد التسمية بعد تفعيل توافق الكتابة المزدوجة

6. تجميع السجلات

(1) السجلات المهيكلة

(1) ▶مثال: إعداد السجلات المهيكلة

PYTHON
# app/core/logging.py
import logging
import json
from datetime import datetime

class JSONFormatter(logging.Formatter):
    def format(self, record):
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
        }
        # إضافة سياق الطلب إذا كان متاحًا
        if hasattr(record, "request_id"):
            log_entry["request_id"] = record.request_id
        if hasattr(record, "user_id"):
            log_entry["user_id"] = record.user_id
        return json.dumps(log_entry)

# إعداد التسجيل
logger = logging.getLogger("pricetracker")
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)

الناتج:

TEXT
# تم تعريف الدالة بنجاح

(2) مقارنة حلول تجميع السجلات

الحل المزايا العيوب السيناريوهات الموصى بها
ELK (Elasticsearch + Logstash + Kibana) ميزات شاملة، قدرات بحث قوية استهلاك موارد عالٍ المشاريع الكبيرة
Loki+Grafana+Promtail خفيف، متكامل مع Grafana قدرات بحث محدودة المشاريع الصغيرة والمتوسطة
CloudWatch Logs بدون صيانة حصر AWS نشر على AWS

(2) ▶مثال: إضافة Loki إلى Docker Compose

YAML
# أضف إلى docker-compose.yml
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    volumes:
      - loki_data:/loki

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - ./docker/promtail.yml:/etc/promtail/config.yml
    depends_on:
      - loki

الناتج:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp

7. يُطلق PriceTracker رسميًا

(1) معالم إنجاز المشروع

100%
gantt
    title الجدول الزمني لتطوير PriceTracker
    dateFormat  YYYY-MM-DD
    section المرحلة 1
    مقدمة FastAPI           :p1a, 2026-01-01, 1d
    التثبيت و UV       :p1b, after p1a, 1d
    معاملات المسار والاستعلام     :p1c, after p1b, 1d
    هيكل الطلب و Pydantic :p1d, after p1c, 1d
    نماذج الاستجابة         :p1e, after p1d, 1d
    مشروع المرحلة 1        :p1f, after p1e, 2d
    
    section المرحلة 2
    Middleware               :p2a, after p1f, 1d
    حقن التبعية     :p2b, after p2a, 1d
    قاعدة البيانات SQLAlchemy      :p2c, after p2b, 2d
    عمليات CRUD          :p2d, after p2c, 1d
    المصادقة JWT       :p2e, after p2d, 2d
    مشروع المرحلة 2         :p2f, after p2e, 2d
    
    section المرحلة 3
    WebSocket                :p3a, after p2f, 1d
    Celery                   :p3b, after p3a, 2d
    رفع الملفات              :p3c, after p3b, 1d
    الاختبار                  :p3d, after p3c, 1d
    التخزين المؤقت                  :p3e, after p3d, 1d
    OpenAPI                  :p3f, after p3e, 1d
    
    section المرحلة 4
    Docker                   :p4a, after p3f, 1d
    الأداء              :p4b, after p4a, 1d
    المراقبة               :p4c, after p4b, 1d
    CI/CD                    :p4d, after p4c, 1d
    
    section المرحلة 5
    تصميم المشروع           :p5a, after p4d, 1d
    تطوير المشروع      :p5b, after p5a, 2d
    نشر المشروع       :p5c, after p5b, 1d

(2) قائمة مراجعة التحقق من النشر

بند التحقق طريقة التحقق معايير النجاح
توفر API curl /health {"status": "healthy"}
تكامل الواجهة الأمامية Bob يستدعي API من الواجهة الأمامية جميع نقاط النهاية تعمل بشكل صحيح
المصادقة تسجيل دخول JWT + نقاط نهاية محمية تسجيل الدخول ناجح؛ يُرجع 401 إذا لم تتم المصادقة
الصلاحيات تحديد معدل Free/Pro/Enterprise محدد بشكل صحيح حسب الخطة
WebSocket اتصال + بث الأسعار استقبال تحديثات فورية
التخزين المؤقت معدل إصابة التخزين المؤقت للمنتجات الشائعة > 80%
المراقبة لوحة Grafana المقاييس تُعرض بشكل طبيعي
التنبيهات محاكاة ارتفاع P99 تنبيه مشغل إشعار
السجلات استعلام Loki سجلات مهيكلة قابلة للبحث
CI/CD نشر مُطلق بدفع tag نشر تلقائي ناجح

❓أسئلة شائعة

س هل يتطلب النشر الأزرق-الأخضر ضعف عدد الخوادم؟
ج نعم، يلزم مجموعتان من البيئات أثناء التبديل. لبيئات K8s، يمكن استخدام التحديثات المتدرجة بدلاً من ذلك، فلا حاجة لموارد إضافية.
س كيف يوزع الإصدار الكناري حركة المرور؟
ج يستخدم Nginx معامل weight (server v2:8000 weight=1; server v1:8000 weight=9;)، بينما يستخدم K8s نشر canary لتعديل عدد النسخ.
س ماذا أفعل إذا حدث قفل جدول أثناء ترحيل قاعدة البيانات؟
ج استخدم CREATE INDEX CONCURRENTLY (لإنشاء فهارس بدون قفل الجداول) وتجنب تنفيذ عبارات DDL خلال ساعات الذروة. رحّل الجداول الكبيرة على دفعات.
س ما الفرق بين السجلات المهيكلة والسجلات العادية؟
ج السجلات المهيكلة بتنسيق JSON، حيث يحتوي كل سجل على حقول ثابتة (timestamp، level، message، request_id)؛ يمكن تحليلها والبحث فيها آليًا. السجلات العادية نص مقروء بشري يصعب على الآلات تحليله.
س ماذا يجب أن أراقب خلال الساعة الأولى بعد النشر؟
ج راقب المقاييس الأساسية الثلاثة على لوحة Grafana: QPS (هل هو طبيعي؟)، زمن الاستجابة P99 (هل ارتفع؟)، ومعدل الخطأ (هل هو > 1%). تحقق أيضًا من مجمع السجلات لأي رسائل ERROR.
س كم يستغرق التراجع؟
ج تراجع Docker يستغرق حوالي 30 ثانية (العودة لإصدار الصورة القديم وإعادة التشغيل). تراجعات قاعدة البيانات تعتمد على تعقيد الترحيل؛ حذف الأعمدة البسيط يستغرق بضع ثوانٍ فقط، بينما الترحيلات المعقدة قد تتطلب إصلاح بيانات.

📖ملخص


📝تمارين

  1. تمرين أساسي (الصعوبة: ⭐): أنشئ قائمة مراجعة نشر لـ PriceTracker (5 بنود لكل من الأمان والأداء والمراقبة) واستخدمها للتحقق من بيئة النشر بندًا ببند. تلميح: راجع جدول قائمة المراجعة في هذا الدرس.
  2. مسألة متقدمة (الصعوبة ⭐⭐): نفذ تسجيل JSON مهيكل (بما في ذلك timestamp و level و message و request_id)؛ أضف middleware تسجيل لحقن request_id في كل طلب؛ وإعداد Docker Compose و Loki لتجميع السجلات. تلميح: JSONFormatter + logging.getLogger("pricetracker")
  3. تحدٍ (الصعوبة: ⭐⭐⭐): أكمل عملية النشر — اكتب سكريبت ترحيل آمن (اتبع مبدأ "أضف فقط، لا تحذف")، إعداد نشر Nginx أزرق-أخضر، ضبط قواعد تنبيه Grafana (P99 > 500 مللي ثانية + معدل الخطأ > 5%)، وأجرِ تحقق إصدار كناري (وجّه 10% من حركة المرور إلى v2 أولاً، ثم حوّل بالكامل). تلميح: CREATE INDEX CONCURRENTLY + تبديل upstream في Nginx

---| العودة إلى الفهرس

Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%