تخطَّ إلى المحتوى

تكوين NGINX

يُنشئ التوفير عبر cloud-init تكوين حافة CDN لـ NGINX محسّنًا بالكامل للأداء. توثّق هذه الصفحة كل طبقة من طبقات التكوين، بدءًا من ضبط kernel وصولًا إلى سلوك الذاكرة المؤقتة وحقن رؤوس الموردين. تم التحقق من جميع الإعدادات تحت اختبار تحميل مستمر لمدة 48 ساعة بذروة 172,540 طلب/ثانية.

الملفالغرض
/etc/sysctl.d/99-cdn-tuning.confضبط شبكة Linux kernel
/etc/systemd/system/nginx.service.d/override.confحدود واصفات الملفات لـ NGINX
/etc/security/limits.d/99-nginx.confالحدود على مستوى نظام التشغيل لمستخدم www-data
/etc/nginx/nginx.confالتكوين الرئيسي لـ NGINX (العمال، المخازن المؤقتة، gzip، التسجيل)
/etc/nginx/conf.d/cdn-edge.confتكوين وكيل CDN (الذاكرة المؤقتة، upstream، الرؤوس)

يُطبَّق عبر /etc/sysctl.d/99-cdn-tuning.conf عند التمهيد.

المعاملالقيمةالافتراضيالغرض
net.core.somaxconn655354096حجم قائمة انتظار الاستماع
net.core.netdev_max_backlog655351000قائمة انتظار الحزم الواردة لكل CPU
net.ipv4.tcp_max_syn_backlog65535256قائمة انتظار طلبات SYN (تمنع الإسقاط عند الذروة)
net.ipv4.tcp_tw_reuse12إعادة استخدام مقابس TIME_WAIT للاتصالات الصادرة
net.ipv4.ip_local_port_range1024-6553532768-60999نطاق المنافذ المؤقتة (64K مقابل 28K)
net.core.rmem_max16 MB212 KBالحد الأقصى لمخزن مقبس الاستقبال
net.core.wmem_max16 MB212 KBالحد الأقصى لمخزن مقبس الإرسال
net.ipv4.tcp_rmem4K/87K/16M4K/131K/6Mمخزن استقبال لكل مقبس (الحد الأدنى/الافتراضي/الأقصى)
net.ipv4.tcp_wmem4K/65K/16M4K/16K/4Mمخزن إرسال لكل مقبس (الحد الأدنى/الافتراضي/الأقصى)
net.ipv4.tcp_fin_timeout1560مهلة FIN_WAIT_2 (تنظيف أسرع للمقابس)
net.ipv4.tcp_keepalive_time3007200بدء مجسّات keepalive بعد 5 دقائق خمول
net.ipv4.tcp_slow_start_after_idle01إبقاء نافذة الازدحام دافئة على الاتصالات الخاملة
net.ipv4.tcp_max_tw_buckets2000000~65536الحد الأقصى لمقابس TIME_WAIT
fs.file-max2097152يتفاوتحد واصفات الملفات على مستوى النظام
vm.swappiness1060تفضيل RAM على swap لبيانات الذاكرة المؤقتة
worker_processes auto; # 4 workers on D4s_v5 (1 per vCPU)
worker_rlimit_nofile 65535; # Per-worker file descriptor limit
events {
use epoll; # Linux-optimized event model
worker_connections 8192; # 4 workers x 8192 = 32,768 max concurrent
multi_accept on; # Accept all pending connections per event loop
accept_mutex off; # Not needed with epoll + reuseport
}

يُعيّن تجاوز Systemd في /etc/systemd/system/nginx.service.d/override.conf القيمة LimitNOFILE=65535 لتتطابق.

المخازن المؤقتة للوكيل

Section titled “المخازن المؤقتة للوكيل”
proxy_buffering on;
proxy_buffer_size 16k; # Header buffer (handles large CDN headers)
proxy_buffers 64 16k; # 1 MB per connection (64 x 16k)
proxy_busy_buffers_size 256k; # Can send 256k to client while still reading

حجم المخزن المؤقت للانشغال البالغ 256k بالغ الأهمية — يجب أن يتجاوز أكبر استجابة مخزّنة (Juice Shop هي 75 KB). كان الإعداد الأصلي 64k يُسبّب تسلسلًا تحت الحمل.

gzip on;
gzip_comp_level 4; # Balance: ~85% of max compression at ~40% CPU
gzip_min_length 256; # Skip tiny responses (gzip header overhead)
gzip_vary on; # Vary: Accept-Encoding for correct caching
gzip_proxied any; # Compress all proxied responses
gzip_types text/plain text/css text/javascript text/xml
application/json application/javascript application/xml
application/xml+rss application/atom+xml
application/ld+json application/manifest+json
image/svg+xml;

ذاكرة التخزين المؤقت للملفات المفتوحة

Section titled “ذاكرة التخزين المؤقت للملفات المفتوحة”
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

تُخزّن واصفات الملفات والبيانات الوصفية للكائنات المخزّنة مؤقتًا، مما يُلغي استدعاءات النظام stat() وopen() على الملفات الساخنة.

keepalive_timeout 65;
keepalive_requests 100000; # Was 1000 — caused connection recycling at 90K req/s

عند 90 ألف طلب/ثانية مع keepalive_requests 1000، كانت الاتصالات تُعاد كل 11 ثانية، مما يُولّد مقابس TIME_WAIT. أدى رفع القيمة إلى 100,000 إلى القضاء على هذه المشكلة كليًا.

log_format cdn '$remote_addr [$time_local] "$request" $status $body_bytes_sent $upstream_cache_status $request_time';
access_log /var/log/nginx/access.log cdn buffer=256k flush=5s;

يتضمّن تنسيق السجل cdn القيمة $upstream_cache_status (HIT/MISS) و$request_time لتحليل زمن الاستجابة. يُقلّل التسجيل المؤقت (256k/flush كل 5 ثوانٍ) من تكلفة الإدخال/الإخراج تحت الحمل العالي.

upstream origin_backend {
server 20.12.78.159:80;
keepalive 256; # Persistent connections per worker to origin
keepalive_timeout 60s;
keepalive_requests 1000;
}

مع 4 عمال × 256 keepalive = 1,024 اتصالًا دافئًا بخادم المصدر. بالاقتران مع proxy_http_version 1.1 وproxy_set_header Connection "", يُلغي هذا تكلفة مصافحة TCP على كل خطأ في الذاكرة المؤقتة.

proxy_cache_path /var/cache/nginx/cdn
levels=1:2
keys_zone=cdn_cache:32m
max_size=25g
inactive=24h
use_temp_path=off;
المعاملالقيمةالغرض
keys_zone=cdn_cache:32mذاكرة مشتركة 32 MBتخزّن ما يقارب 256,000 مفتاح ذاكرة مؤقتة وبيانات وصفية
max_size=25gحد القرص 25 GBيستخدم معظم قرص نظام التشغيل البالغ 30 GB؛ إخلاء LRU عند الحد
inactive=24hمهلة عدم نشاط 24 ساعةيُخلى المحتوى غير المُوصَل إليه لمدة 24 ساعة (ليس نفس TTL)
use_temp_path=offالكتابة مباشرةً إلى دليل الذاكرة المؤقتةتجنّب نقل الملفات عبر أنظمة ملفات مختلفة
proxy_cache cdn_cache;
proxy_cache_valid 200 301 302 4h;
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_lock on;
proxy_cache_lock_age 3s;
proxy_cache_lock_timeout 3s;
proxy_cache_background_update on;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
proxy_ignore_headers Set-Cookie Cache-Control Expires Vary;
proxy_hide_header X-Cache-Status;
proxy_hide_header Vary;
التوجيهالقيمةالغرض
proxy_cache_valid 200 301 302 4hTTL مدته 4 ساعاتالمحتوى المخزّن صالح لمدة 4 ساعات (زِيد لتقليل انخفاضات الإنتاجية عند موجة التحديث)
proxy_cache_lock onمنع thundering herdطلب واحد فقط يصل إلى خادم المصدر لكل URL غير مخزّن؛ الآخرون ينتظرون ملء الذاكرة المؤقتة
proxy_cache_lock_age 3sمهلة القفلإذا لم يكتمل الطلب الأول خلال 3 ثوانٍ، يُسمح لطلب آخر بالمرور
proxy_cache_background_update onتحديث بدون زمن استجابةيُقدّم المحتوى القديم فورًا بينما يُحدَّث في الخلفية
proxy_cache_use_staleالمرونةيُقدّم المحتوى القديم أثناء أخطاء خادم المصدر (500/502/503/504) أو أثناء التحديث
proxy_ignore_headersفرض التخزين المؤقتيتجاهل Set-Cookie وCache-Control وExpires وVary من خادم المصدر — يقرر CDN قيم TTL وسلوك Vary (تُرسل Juice Shop القيمة max-age=0 وثلاثة رؤوس Vary التي تمنع التخزين المؤقت الفعّال)
proxy_hide_header X-Cache-Statusإزالة رأس خادم المصدريُضيف NGINX الخاص بخادم المصدر رأسه الخاص X-Cache-Status — يُزال ليظهر فقط حالة الذاكرة المؤقتة لـ CDN
proxy_hide_header Varyمنع تجزئة الذاكرة المؤقتةيُرسل خادم المصدر رؤوس Vary: Accept-Encoding متعددة. يمنع إزالتها تجزئة مفتاح الذاكرة المؤقتة عبر تباديل Accept-Encoding. يُضيف gzip_vary on في NGINX رأس Vary الصحيح الفردي تلقائيًا
proxy_read_timeout 30s;
proxy_connect_timeout 10s;
proxy_send_timeout 15s;

يمنح خادم المصدر وقتًا أطول للاستجابة تحت الحمل مع الإخفاق السريع في مشكلات الاتصال.

server {
listen 80 reuseport; # Kernel distributes connections across all 4 workers
server_name _;
}

يُفعّل reuseport الخيار SO_REUSEPORT — يوزّع kernel الاتصالات الواردة مباشرةً على عمليات العمال، مما يُلغي تنافس accept mutex.

يحقن المحاكي رؤوسًا من جميع موردي CDN الخمسة الرئيسيين في وقت واحد. يتيح هذا تكوين F5 XC بـ “Trusted Client IP Header” الخاص بأي مورد ورؤية حمولات الرؤوس الواقعية بصرف النظر عن CDN الذي يُحاكَى.

الرؤوس القياسية للصناعة (جميع CDNs)

Section titled “الرؤوس القياسية للصناعة (جميع CDNs)”
الرأسالقيمةالغرض
X-Forwarded-Forسلسلة IP العميلIP المُحوَّل القياسي
X-Forwarded-Protohttp أو httpsبروتوكول العميل الأصلي
X-Forwarded-Hostاسم المضيف الأصليرأس Host الأصلي
X-Forwarded-Portمنفذ الخادمالمنفذ الأصلي
X-Real-IPIP العميلIP عميل واحد (اصطلاح nginx)
Via1.1 cdn-simulatorتعريف الوكيل
Forwardedتنسيق RFC 7239رأس إعادة التوجيه الموحّد
CDN-Loopcdn-simulatorاكتشاف الحلقات
الرأسالقيمةالغرض
True-Client-IPIP العميلعنوان IP الأصلي للمستخدم النهائي
X-Akamai-Edgescapeسلسلة جغرافية مركّبةgeoregion, country_code, region_code, city, dma, pmsa, msa, areacode, county, fips, lat, long, timezone, zip, continent, throughput, bw, network, asnum, network_type
X-Akamai-Device-Characteristicsخصائص الجهازbrand_name, model_name, is_mobile, is_tablet, is_wireless_device, device_os, device_os_version, resolution_width, resolution_height
X-Akamai-Request-IDUUID الطلبمعرّف الطلب الفريد
الرأسالقيمةالغرض
CF-Connecting-IPIP العميلIP العميل الحقيقي (موجود دائمًا)
CF-IPCountryUSرمز البلد المكوّن من حرفين
cf-ipcitySan Joseمدينة العميل
cf-ipcontinentNAرمز القارة
cf-iplatitude / cf-iplongitudeالإحداثياتالموقع الجغرافي
cf-region / cf-region-codeCalifornia / CAمعلومات المنطقة
cf-metro-code807رمز المنطقة الحضرية الأمريكية
cf-postal-code95113الرمز البريدي
cf-timezoneAmerica/Los_Angelesمنطقة زمنية IANA
Cf-Ray{request_id}-SJCمعرّف ray فريد مع رمز IATA لنقطة التواجد
CF-Visitor{"scheme":"https"}معلومات بروتوكول الزائر
cf-bot-score85درجة البوت (1=بوت، 99=إنسان)
cf-verified-botfalseعلامة البوت الجيد المعروف
cf-ja3-hashe7d705a3286e19ea42f587b344ee6865بصمة JA3 لـ TLS
cf-ja4t13d1516h2_8daaf6152771_b0da82dd1658بصمة JA4 لـ TLS
الرأسالقيمةالغرض
CloudFront-Viewer-AddressIP:portIP العميل ومنفذ المصدر
CloudFront-Viewer-CountryUSرمز البلد
CloudFront-Viewer-Country-NameUnited Statesالاسم الكامل للبلد
CloudFront-Viewer-Country-RegionCAرمز المنطقة
CloudFront-Viewer-Country-Region-NameCaliforniaالاسم الكامل للمنطقة
CloudFront-Viewer-CitySan Joseمدينة العميل
CloudFront-Viewer-Postal-Code95113الرمز البريدي
CloudFront-Viewer-Latitude / Longitude37.33530 / -121.89300الموقع الجغرافي
CloudFront-Viewer-Time-ZoneAmerica/Los_Angelesمنطقة زمنية IANA
CloudFront-Viewer-Metro-Code807رمز المنطقة الحضرية الأمريكية
CloudFront-Viewer-ASN7018رقم النظام المستقل
CloudFront-Viewer-Http-Version2.0إصدار HTTP للعميل
CloudFront-Forwarded-Protohttpsالبروتوكول الأصلي
CloudFront-Viewer-TLSTLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumedتفاصيل TLS
CloudFront-Viewer-JA3-Fingerprinte7d705a3286e19ea42f587b344ee6865بصمة JA3 لـ TLS
CloudFront-Is-Desktop-Viewertrue/falseاكتشاف الجهاز
CloudFront-Is-Mobile-Viewertrue/falseاكتشاف الجهاز
CloudFront-Is-Tablet-Viewertrue/falseاكتشاف الجهاز
CloudFront-Is-SmartTV-Viewerfalseاكتشاف الجهاز
X-Amz-Cf-Idمعرّف مشفّرمعرّف طلب CloudFront
الرأسالقيمةالغرض
Fastly-Client-IPIP العميلIP العميل الحقيقي
Fastly-SSL1الاتصال كان عبر TLS
Fastly-Client1طلب مواجه للعميل (وليس shield)
Fastly-FFcache-sjc3120-SJCتعريف عقدة الذاكرة المؤقتة
X-Geo-Country-CodeUSالبلد (اصطلاح متغيّر VCL)
X-Geo-Country-Code3USAرمز البلد المكوّن من ثلاثة أحرف
X-Geo-Country-NameUnited Statesالاسم الكامل للبلد
X-Geo-CitySan Joseمدينة العميل
X-Geo-RegionCAرمز المنطقة
X-Geo-Continent-CodeNAالقارة
X-Geo-Latitude / X-Geo-Longitude37.3353 / -121.8938الموقع الجغرافي
X-Geo-Postal-Code95113الرمز البريدي
X-Geo-Metro-Code807رمز المنطقة الحضرية الأمريكية
X-Geo-ASN7018رقم النظام المستقل
X-Geo-Conn-Speedbroadbandفئة سرعة الاتصال
X-Geo-Conn-Typewiredنوع الاتصال
الرأسالقيمةالغرض
X-Azure-ClientIPIP العميلعنوان IP العميل
X-Azure-SocketIPIP العميلعنوان IP المصدر لمقبس TCP
X-Azure-Refسلسلة مرجعية مشفّرةمرجع طلب فريد لاستكشاف الأخطاء
X-Azure-FDIDa0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1معرّف مورد Front Door
X-Azure-RequestChainhops=1عدد قفزات اكتشاف الحلقات

رؤوس الاستجابة (تُضاف إلى استجابات العميل)

Section titled “رؤوس الاستجابة (تُضاف إلى استجابات العميل)”
الرأسالقيمالغرض
X-Cache-StatusHIT, MISS, EXPIRED, STALE, UPDATINGسلوك الذاكرة المؤقتة لهذا الطلب
X-CDN-Edgecdn-simulatorيُعرّف عقدة الحافة هذه
X-CDN-POPSJCرمز IATA لنقطة التواجد المحاكاة
X-Served-Bycache-sjc3120-SJCعقدة الذاكرة المؤقتة المحاكاة بتنسيق Fastly
X-Request-IDUUID (لكل طلب)معرّف الطلب الفريد

يكتشف المحاكي نوع الجهاز من رأس User-Agent باستخدام توجيهات NGINX map:

  • محمول: يطابق iPhone، Android (غير اللوحي)، iPod، BlackBerry، Opera Mini، IEMobile
  • لوحي: يطابق iPad، لوحي Android، Kindle، PlayBook
  • سطح مكتب: الافتراضي عند عدم تطابق المحمول أو اللوحي

ينعكس نوع الجهاز في:

  • CloudFront-Is-Desktop-Viewer / CloudFront-Is-Mobile-Viewer / CloudFront-Is-Tablet-Viewer
  • X-Akamai-Device-Characteristics (حقول is_mobile وis_tablet وis_wireless_device)
Terminal window
ssh azureuser@<PUBLIC_IP>
# Update upstream server
sudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Clear cache and reload
sudo rm -rf /var/cache/nginx/cdn/*
sudo nginx -t && sudo systemctl reload nginx

أو حدّث origin_host في terraform.tfvars وشغّل terraform apply لإعادة التوفير.

Terminal window
ssh azureuser@<PUBLIC_IP>
sudo rm -rf /var/cache/nginx/cdn/*
sudo systemctl reload nginx

التحقق من إحصائيات الذاكرة المؤقتة

Section titled “التحقق من إحصائيات الذاكرة المؤقتة”
Terminal window
# Object count and disk usage
sudo find /var/cache/nginx/cdn -type f | wc -l
sudo du -sh /var/cache/nginx/cdn
# Recent access log with cache status
tail -20 /var/log/nginx/access.log
Terminal window
# Real-time connections and socket states
ss -s
# NGINX worker CPU usage
top -bn1 | grep nginx
# Upstream keepalive connections
ss -tn state established dst <ORIGIN_IP> | wc -l
# TIME_WAIT socket count
ss -tn state time-wait | wc -l

تم التحقق منها تحت اختبار تحميل مستمر لمدة 48 ساعة:

المقياسالقيمة
ذروة الإنتاجية (مخزّنة)172,540 طلب/ثانية
الإنتاجية المستدامة (مخزّنة)85,000-103,000 طلب/ثانية
ذروة الاتصالات15,000 متزامن
نسبة إصابة الذاكرة المؤقتة100% (عند الإحماء)
الذاكرة تحت الحمل1.2 GB مستقرة (8% من 16 GB)
CPU عند الذروة100% (4 أنوية - CPU هو السقف)
الأخطاء خلال اختبار 48 ساعة0
تسريبات الذاكرةلم تُكتشف
تسريبات الاتصالاتلم تُكتشف