البحث في الموقع
المحتوى عن 'وسيط'.
-
الوسيط العكسي عبارة عن نوع من الخواديم الوسيطة Proxy servers تستقبل طلبات HTTP(S) وتوزّعها بصورة شفّافة على خادوم خلفيّ Backend server واحد أو أكثر. الوسيط العكسي مُفيد لأنّ مُعظم تطبيقات الويب في أيّامنا هذه تستعمل خواديم لم تكن قد صُمّمت لأخذ الطّلبات مُباشرة من المُستخدم وفي العادة لا تدعم إلّا ميزات HTTP بدائيّة. يُمكنك استخدام وسيط عكسيّ لتجنّب وصول المستخدم إلى الخواديم الخلفيّة مُباشرة. يُمكن استخدامها كذلك لتوزيع الحمل Load balancing من الطّلبات على عدّة خواديم، ما يُحسّن الأداء ويُوفّر حماية من تعطّل التّطبيق. يُمكها كذلك أن تمنحك ميزات لا تمنحها خواديم التّطبيقات مثل التّخبئة Caching، ضغط الملفّات Compression، وحتى تشفير SSL. سنضبُط في هذا الدّرس Apache ليعمل على وسيطًا عكسيًّا بسيطًا باستخدام وحدة mod_proxy لإعادة توجيه الطّلبات القادمة إلى خادوم خلفيّ أو أكثر من خادوم يعمل على نفس الشّبكة. سنستعمل في هذا الدّرس واجهة خلفيّة بسيطة مكتوبة بإطار العمل Flask، لكنّك تستطيع استعمال أي خادوم خلفيّ تُريده وأي لغة برمجيّة مُناسبة لك. مُلاحظة: أبدِل your_server_ip في عناوين URL التي تجدها في هذا الدّرس بعنوان IP الخاصّ بخادومك. المُتطلّبات لاتّباع هذا الدّرس، ستحتاج إلى: خادوم أوبونتو 16.04 مضبوط باتّباع الخطوات في هذا الدّرس، وذلك يشمل مُستخدما ذا صلاحيّات sudo مع ضبط مُسبق لتمكينه من تنفيذ مهام إداريّة، غير المستخدم الجذر root، بالإضافة إلى جدار ناري. Apache 2 مُنصّب على خادومك باتّباع الخطوة الأولى من هذا الدّرس. الخطوة الأولى – تفعيل وحدات Apache اللازمة يمتلك Apache الكثير من الوحدات المبنيّة مُسبقا لكنّها لا تكون مُفعّلة عند التّنصيب. لذا سيتوجّب علينا تفعيل الوحدات التي سنستخدمها في هذا الدّرس. الوحدات التّي نحتاج إليها هي mod_proxy وبضعة إضافات خاصّة بها للحصول على بضعة ميزات أخرى لدعم بروتوكولات شبكيّة مُتعدّدة. سنستعمل ما يلي بالتّحديد: mod_proxy، الوحدة الرّئيسيّة لإعادة توجيه الطّلبات، وتُمكّننا من تحويل Apache إلى بوابّة لخواديم التّطبيقات المُعتمدة. وحدة mod_proxy_http لتمكيننا من توسيط اتّصالات HTTP. وحدتا mod_proxy_balancer وmod_lbmethod_byrequests لإضافة ميّزات مُوازنة الحمل على عدّة خواديم. لتفعيل الوحدات الأربع، نفّذ الأوامر التّاليّة: sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_balancer sudo a2enmod lbmethod_byrequests لتطبيق التّغييرات، أعد تشغيل Apache: sudo systemctl restart apache2 يُمكن الآن استخدام Apache ليعمل وسيطًا عكسيًّا لطلبات HTTP. في الخطوة – الاختياريّة - التّاليّة، سننشئ خادومين خلفيّين بسيطين. ما سيُخوّلنا التّحقّق من أنّ الإعدادات تعمل جيّدا، لكن إن كانت لديك تطبيقات تعمل في الواجهة الخلفيّة، يُمكنك تخطي الخطوة التّاليّة والانتقال مُباشرة إلى الخطوة الثّالثة. الخطوة الثّانيّة – إعداد خواديم خلفيّة Backend Servers للاختبار إنشاء خواديم خلفيّة بسيطة طريقة سهلة لاختبار ما إذا كانت إعدادات Apache الخاصّة بك تعمل جيّدًا أو لا. في هذه الفقرة، سنعدّ خادومين يجيبان على طلبات HTTP بمقطع نصّي صغير. أحد الخادومين سيُجيب بالمقطع Hello world! والآخر بالمقطع Howdy world!. مُلاحظة: في الحالات غير الاختباريّة، عادة ما يجب على الخواديم أن تُجيب بنفس الإجابة. لكن بالنّسبة لهذا الاختبار، فامتلاك إجابتين مُختلفتين يُمكّننا من التّأكّد من أنّ خاصيّة مُوازنة الحمل تستخدم كلا الخادومين. Flask إطار عمل مُصغّر مبني بلغة بايثون لبناء تطبيقات الويب. استعملنا Flask لإنشاء خادوميْ الاختبار لأنّ تطبيقا بسيطا باستخدامه لا يتطلّب سوى بضعة أسطر برمجيّة. ليس من الضّروري أن تكون لديك معرفة بلغة بايثون لإعداد الخادومين، لكن إن أردت تعلّمها، فيُمكنك الاطّلاع على هذه الدّروس. أولا، حدّث قائمة الحزم: sudo apt-get update بعدها، نصّب أداة pip لإدارة حزم لغة بايثون: sudo apt-get -y install python3-pip استخدام pip لتنصيب أداة Flask: sudo pip3 install flask بعد تنصيب المُكوّنات المطلوبة، ابدأ بإنشاء ملفّ جديد ليحتوي على شفرة الخادوم الأول في المُجلّد الشخصي للمستخدم الحاليّ: nano ~/backend1.py انسخ ما يلي إلى الملفّ ثمّ احفظه وأغلقه: from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Hello world!' السّطران الأول والثّاني عبارة عن تهيئة لإطار العمل Flask. لدينا دالّة واحدة باسم home() تُرجع النّص Hello world!. السّطر @app.route('/') المتواجد فوق الدّالة home() يُخبر Flask بالإجابة على أي طلب يصل إلى العنوان الجذر / بما تُرجعه الدّالّة. الخادوم الثّاني مُشابه للأول، الاختلاف الوحيد أنّ الجواب مُختلف قليلا. لذا انسخ الملفّ الأول: cp ~/backend1.py ~/backend2.py عدّل الملفّ الجديد: nano ~/backend2.py عدّل ما تُرجعه الدّالة من Hello world! إلى Howdy world! ثمّ احفظ وأغلق الملفّ. from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Howdy world!' استخدم الأمر التّالي لتشغيل الخادوم الأول على المنفذ رقم 8080. سيقوم هذا الأمر بتحويل المخرجات إلى /dev/null كذلك لتفادي مُقاطعة المُخرج للطّرفيّة. FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 & في السّطر أعلاه، عرّفنا مُتغيّر البيئة FLASK_APP ثمّ نفّذنا الأمر flask لتشغيل الخادوم في نفس السّطر. مُتغيّرات البيئة طريقة سهلة لتمرير المعلومات إلى العمليّات المبدوءة على الطّرفيّة. في هذه الحالة، باستعمال مُتغيّرات البيئة فإنّنا نتأكّد من أنّ الإعداد يُطبّق على الأمر الذي سيكون قيد التّشغيل فقط ولن يكون مُتوفّرا بعد ذلك، وهذا مُناسب لنا لأنّنا سنمرّر اسم ملفّ آخر بنفس الطّريقة لإخبار flask بتشغيل الخادوم الثّاني. استعمل الأمر التّالي لتشغيل الخادوم الثّاني على المنفذ 8081 بطريقة مُشابهة لما سبق. لاحظ بأنّ قيمة مُتغيّر البيئة FLASK_APP مُختلفة في هذه الحالة: FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 & يُمكنك اختبار عمل الخادومين باستخدام أداة curl. اختبار الخادوم الأول: curl http://127.0.0.1:8080/ يجب على المُخرج أن يساوي Hello world!. الخادوم الثّاني: curl http://127.0.0.1:8081/ يجب على المُخرج أن يكون Howdy world!. مُلاحظة: لإغلاق كلا الخادومين بعد أن تنتهي من استخدامهما، عند إنهائك لهذا الدّرس مثلا، فيُمكنك تنفيذ الأمر killall flask. في الخطوة التّاليّة، سنعدّل ملفّ إعدادات Apache لتمكيننا من استخدامه وسيطًا عكسيًّا. الخطوة الثّالثة – تعديل الإعدادات المبدئيّة لجعل Apache يعمل وسيطًا عكسيًّا سنعدّ في هذه الفقرة مُضيفًا افتراضيًّا Virtual host على Apache للعمل وسيطًا عكسيًّا لخادوم خلفي واحد أو عدّة خواديم موزونة الحمل. مُلاحظة: سنُطبّق الإعدادات في هذا الدّرس على مُستوى المُضيف الافتراضي. يوجد في الإعداد المبدئي لـApache مُضيف افتراضي واحد مُفعّل. لكنّك تستطيع استعمال جميع أجزاء هذه الإعدادات على أي مُضيف افتراضي آخر. إن كان خادوم Apache الخاص بك يجيب على طلبات HTTP و HTTPS، فسيتوجّب عليك وضع إعدادات الوسيط العكسي في كلا المُضيفَين الافتراضيّيْن لـHTTP وHTTPS. افتح ملفّ إعدادات Apache المبدئي باستخدام nano أو أي مُحرّر مُفضّل لديك: sudo nano /etc/apache2/sites-available/000-default.conf ستجد داخل هذا الملفّ الجزء <VirtualHost *:80> بدءا من السّطر الأول. يشرح المثال الأول أسفله كيفيّة ضبط هذا الجزء لإعداد وسيط عكسي لخادوم واحد، وفي المثال الثّاني سنضبط وسيطا عكسيّا يوازن الحمل على أكثر من خادوم. المثال الأول – إعداد وسيط عكسي لخادوم خلفيّ واحد أبدل جميع المُحتويات داخل الوسم VirtualHost بما يلي ليصير ملفّ الإعدادات الخاصّ بك كما يلي: <VirtualHost *:80> ProxyPreserveHost On ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ </VirtualHost> إن تابعت الأمثلة في الخطوة الثّانيّة أعلاه، فاستخدم العنوان 127.0.0.1:8080 كما هو مكتوب أعلاه. إن كان لديك تطبيق ويب خاصّ بك، فاستعمل عنوان التّطبيق عوضا عمّا فعلنا. لدينا ثلاثة تعليمات في هذا الإعداد: ProxyPreserveHost مسؤولة عن جعل Apache يُمرّر الترويسة Header المسمَّاة Host الأصليّة إلى الخادوم الخلفيّ. هذا الأمر مُفيد لأنّه يُخبر الخادوم بالعنوان المُستخدَم للوصول إلى التّطبيق. ProxyPass عبارة عن تعليمة الإعداد الرّئيسيّة للوسيط. في هذه الحالة، نحدّد كلّ شيء تحت عنوان URL الجذر / ليُربط مع الخادوم الخلفيّ المرتبط بالعنوان المُعطى. على سبيل المثال، إن استقبل Apache طلبا للموجّه /example، فسيقوم بالاتّصال بالعنوان http://your_backend_server/example وإرجاع الإجابة إلى العميل. ينبغي على ProxyPassReverse أن يحمل نفس الإعداد الذي يحمله ProxyPass. ويُخبر Apache بتعديل ترويسة الجواب من طرف الخادوم الخلفيّ. بهذه الطّريقة سنتأكّد من إعادة توجيه العميل إلى عنوان الوسيط وليس الخادوم الخلفيّ في حالة وُجدت ترويسة إعادة توجيه في جواب الخادوم لتجنّب أخطاء إعادة التّوجيه. لتطبيق هذه التّغييرات، أعد تشغيل Apache: sudo systemctl restart apache2 إن حاولت الآن الوصول إلى http://your_server_ip في مُتصفّح ويب، ستجد جواب الخادوم الخلفيّ عوضا عن رسالة ترحيب Apache المألوفة. إن تابعت الخطوة الثّانيّة، فهذا يعني بأنّ النّتيجة ستكون Hello world!. المثال الثّاني – موازنة الحمل على عدّة خواديم خلفيّة إن كان لديك أكثر من خادوم خلفيّ واحد، فاستخدام ميزة مُوازنة الحمل في mod_proxy طريقة جيّدة لتوزيع الطّلبات على الخواديم. استبدل جميع مُحتويات الجزء VirtualHost بما يلي ليبدو ملفّ الإعدادات كما يلي: <VirtualHost *:80> <Proxy balancer://mycluster> BalancerMember http://127.0.0.1:8080 BalancerMember http://127.0.0.1:8081 </Proxy> ProxyPreserveHost On ProxyPass / balancer://mycluster/ ProxyPassReverse / balancer://mycluster/ </VirtualHost> الإعدادات هنا مُشابهة لما سبق، لكن عوضا عن تخصيص خادوم واحد مُباشرة، استعملنا وسم Proxy إضافيّا لتعيين خواديم مُتعدّدة.سمّينا الوسم بـbalancer://mycluster (يُمكنك تغيير الاسم إن شئت) ليحتوي على أكثر من تعليمة BalancerMember، والذي يُحدّد عناوين الخواديم الخلفيّة. هكذا تستعمل التّعليمتان ProxyPass وProxyPassReverse مجموعة موازنة الحمل المُسمّاة mycluster عوضا عن خادم مُحدّد. إن تابعت الخطوة الثّانيّة من هذا الدّرس، فاستعمل العنوانين 127.0.0.1:8080 و127.0.0.1:8081 للتّعليمة BalancerMember كما هو مُبيّن في الإعدادات أعلاه. أمّا إن كانت لديك خواديم خاصّة بك فاستعمل عناوينها. لتطبيق هذه التّغييرات، أعد تشغيل Apache: sudo systemctl restart apache2 إن حاولت الآن الوصول إلى http://your_server_ip في مُتصفّح ويب، ستجد جواب الخواديم الخلفيّة عوضا عن رسالة ترحيب Apache المألوفة. إن تابعت الخطوة الثّانيّة، فعند إعادة تحميل الصّفحة عدّة مرّات، ستُلاحظ بأنّ النّتيجة ستكون إمّا Hello world! أو Howdy world!، ما يعني بأنّ الوسيط العكسي يعمل على مُوازنة الحمل بين الخادومين. خاتمة لديك الآن معرفة بكيفيّة إعداد خادوم Apache ليعمل وسيطًا عكسيًّا لخادوم تطبيق أو أكثر. يُمكن استعمال mod_proxy لضبط وسيط عكسي لخواديم تطبيقات مكتوبة بلغات مثل Python مع Django أو Ruby مع Ruby on Rails. يُمكن كذلك استخدامها لموازنة الحمل على عدّة خواديم للتّطبيقات التي تستقبل العديد من الزّوار، بالإضافة إلى إمكانيّة استخدامه لتوفير حماية SSL للخواديم الخلفيّة التي لا تدعم SSL. رغم أنّ mod_proxy وmod_proxy_http أكثر تركيب يتمّ استخدامه، إلّا أنّ هناك العديد من الوحدات الأخرى التّي تدعم بروتوكولات اتّصال أخرى. إليك بعضا من الوحدات الشّهيرة التي لم نستخدمها في هذا الدّرس: mod_proxy_ftp لبروتوكول FTP. mod_proxy_connect لإعداد أنفاق SSL. mod_proxy_ajp لبروتوكول AJP (Apache JServ Protocol) لخواديم خلفيّة مبنيّة على Tomcat. mod_proxy_ftp لمقابس الويب Web sockets. يُمكنك قراءة التّوثيق الرّسمي للاستزادة حول mod_proxy. ترجمة – بتصرّف - للمقال How To Use Apache as a Reverse Proxy with mod_proxy on Ubuntu 16.04 لكاتبه Mateusz Papiernik.
-
- reverse proxy
- mod_proxy
-
(و 2 أكثر)
موسوم في:
-
سنتعلّم في هذا الدّرس كيفيّة استخدام HAProxy (والذي يرمز إلى الوسيط عالي التوفّر High Availability Proxy) كمُوازِن حمل عن طريق الطبقة السّابعة layer 7 load balancer من أجل تخديم تطبيقات متعدّدة من اسم مجال واحد Single Domain أو عنوان IP، بإمكان موازنة الحمل أن تزيد أداء، توفّر، ومرونة بيئتنا. تكون موازنة الحمل والوسيط العكسي للطبقة 7 ملائمة لموقعك إن أردت أن تملك اسم نطاق واحد يقوم بتخديم تطبيقات متعدّدة، حيث يمكن تحليل طلبات http لتقرّر أي تطبيق ينبغي عليه أن يستقبل حركة مرور البيانات. تمّت كتابة هذا الدّرس باستخدام ووردبريس وموقع ثابت Static website كأمثلة، ولكن يمكن استخدام مفاهيمه العامّة مع تطبيقات أخرى للحصول على تأثير مماثل. المتطلبات الأساسية قبل متابعة هذا الدّرس ينبغي عليك أن تملك تطبيقين على الأقل يعملان على خادومين منفصلين، سنستخدم موقعًا ثابتًا مستضافًا على Nginx و ووردبريس كتطبيقين لدينا، وبالإضافة للبيئة الحاليّة لديك سنقوم بإنشاء الخواديم التالية: haproxy-www: وهو خادوم HAProxy لأجل موازنة الحمل والوسيط العكسي wordpress-2: وهو خادوم الويب الثاني لووردبريس (تحتاجه فقط إن أردت موازنة حمل مكونات ووردبريس في بيئتك) web-2: خادوم ويب Nginx الثاني (تحتاجه فقط إن أردت موازنة حمل مكونات Nginx في بيئتك) إن لم يسبق لك التّعامل مع المفاهيم أو المصطلحات الأساسيّة لموازنة الحمل، مثل موازنة الحمل عن طريق الطبقة 7 أو الواجهات الخلفيّة backends أو قوائم تحكّم الوصول ACLs فهذا هو الدّرس الذي يشرح الأساسيّات: مقدّمة إلى HAProxy ومبادئ موازنة الحمل (Load Balancing). هدفنا بنهاية هذا الدّرس نريد أن نحصل على بيئة تبدو كما يلي: أي سيقوم المستخدمون لديك بالنفاذ لكلا تطبيقيك عبر http://example.com، وسيتم تمرير كل الطلبات التي تبدأ بـ http://example.com/wordpress إلى خواديم ووردبريس، ويتم تمرير جميع باقي الطلبات إلى خواديم Nginx الأساسيّة، لاحظ أنّه لا تحتاج بالضرورة لموازنة حمل تطبيقاتك حتى تظهر على مجال واحد، ولكن سنقوم بتغطية موازنة الحمل في هذا الدّرس. تثبيت HAProxy نقوم بإنشاء خادوم جديد مع الشّبكات الخاصّة، سنسمّيه في هذا الدّرس haproxy-www. نقوم بتثبيت HAProxy على الخادوم haproxy-www باستخدام apt-get: sudo apt-get update sudo apt-get install haproxy نحتاج لتمكين سكريبت التهيئة init script لـ HAProxy كي يبدأ ويتوقف HAProxy مع الخادوم لدينا: sudo vi /etc/default/haproxy نغيّر قيمة ENABLED إلى 1 لتمكين سكريبت التهيئة لـ HAProxy: ENABLED=1 نقوم بالحفظ والخروج، سيبدأ ويتوقف HAProxy الآن مع خادومنا، نستطيع أيضًا الآن استخدام الأمر service للتحكّم بـ HAProxy، فلنتحقّق من أنّه قيد التشغيل: user@haproxy-www:/etc/init.d$ sudo service haproxy status haproxy not running. نجد أنّه لا يعمل، لا مشكلة لأنّه يحتاج إلى إعداده قبل أن نتمكّن من استخدامه، فلنقم الآن بإعداد HAProxy لأجل بيئتنا. إعداد HAProxy يكون ملف إعدادات HAProxy مُقسّمًا إلى قسمين رئيسيين: العمومي Global: يقوم بتعيين المُعامِلات parameters على نطاق العمليّة الوسطاء Proxies: يتكون من المُعامِلات الافتراضيّة defaults، الاستماع listen، الواجهة الأماميّة frontend، والواجهة الخلفيّة backend. مرّة أخرى إن لم يسبق لك أن سمعت عن مفاهيم أو المصطلحات الأساسيّة لموازنة الحمل، فقم بالرجوع إلى هذا الدّرس: مقدّمة إلى HAProxy ومبادئ موازنة الحمل (Load Balancing). إعداد HAProxy: العمومي يجب أن يتم ضبط إعدادات HAProxy على الخادوم haproxy-www. في البداية لنقم بعمل نسخة من الملف haproxy.cfg الافتراضي: cd /etc/haproxy; sudo cp haproxy.cfg haproxy.cfg.orig نقوم الآن بفتح الملف haproxy.cfg باستخدام مُحرِّر نصوص: sudo vi /etc/haproxy/haproxy.cfg سنشاهد وجود قسمين معرّفين مسبقًا: global و defaults، سنلقي نظرة في البداية على بعض المعاملات القياسية default. تحت القسم defaults نبحث عن الأسطر التالية: mode http option httplog يقوم اختيار http كوضع بضبط HAProxy ليعمل كموازن حمل عن طريق الطبقة 7 (أو طبقة التطبيقات)، يعني هذا أنّ موازن الحمل سينظر إلى محتوى طلبات http ويقوم بتمريرها إلى الخادوم المناسب اعتمادًا على القواعد المعرّفة في الواجهة الأماميّة frontend، إن لم يكن هذا المفهوم مألوفًا لديك فمن فضلك اقرأ قسم أنواع موازنة الحمل في درس مقدّمة إلى HAProxy. لا تقم بإغلاق ملف الإعدادات الآن، لأنّنا سنضيف إعدادات الوسيط. إعداد HAProxy: الوسطاء إعداد الواجهة الأماميّة أول شيء نريد إضافته هو واجهة أماميّة frontend، ولأجل إعداد أساسي لوسيط عكسي وموازنة حمل عن طريق الطبقة 7 سنحتاج لتعريف قائمة تحكّم وصول ACL تُستخدَم لتوجيه حركة مرور بياناتنا إلى خواديم الواجهة الخلفيّة المناسبة، هنالك العديد من قوائم تحكّم الوصول التي يُمكن استخدامها في HAProxy، سنغطي فقط واحدة منها في هذا الدّرس (وهي path_beg)، ولأجل الحصول على قائمة كاملة من قوائم تحكّم الوصول في HAProxy قم بمراجعة التّوثيق الرسميّ: HAProxy ACLs. نضيف واجهتنا الأماميّة www في نهاية الملف، تأكّد من أن تضع عنوان IP الخاص بخادوم haproxy-www لديك بدلًا من haproxy_www_public_IP: frontend www bind haproxy_www_public_IP:80 option http-server-close acl url_wordpress path_beg /wordpress use_backend wordpress-backend if url_wordpress default_backend web-backend وهذا شرح لما يعنيه كل سطر من المقطع السابق المأخوذ من إعدادات الواجهة الأماميّة: frontend www: يُعيِّن واجهة أماميّة اسمها "www"، حيث سنستخدمها للتعامل مع حركة مرور بيانات www الواردة. bind haproxy_www_public_IP:80: ضع عنوان IP خادوم haproxy-www لديك بدلًا من haproxy_www_public_IP، يُخبر هذا السطر HAProxy أنّ هذه الواجهة الأماميّة ستتعامل مع حركة مرور بيانات الشبكة الواردة إلى عنوان IP هذا على هذا المنفذ. option http-server-close: يقوم بتمكين وضع إغلاق اتصال HTTP على الخادوم، ويحافظ على القدرة على دعم ترويسة HTTP keep-alive وتقنيّة HTTP pipelining على العميل (وهي تقنيّة لإرسال العديد من طلبات HTTP ضمن اتصال TCP وحيد بدون انتظار الموافقة لها)، يسمح هذا الخيار بأن يقوم HAProxy بمعالجة طلبات متعدّدة للعميل ضمن اتصال وحيد، والذي عادة ما يزيد من الأداء. acl url_wordpress path_beg /wordpress: يُعيِّن قائمة تحكّم وصول ACL تُدعى url_wordpress والتي تكون قيمتها صحيحة true إن كان مسار الطلب يبدأ بـ "wordpress/"، على سبيل المثال http://example.com/wordpress/hello-world. use_backend wordpress-backend if url_wordpress: يقوم بإعادة توجيه أي حركة مرور بيانات تتوافق مع قائمة تحكّم الوصول url_wordpress إلى wordpress-backend، والتي سنقوم بتعريفها قريبًا. default_backend web-backend: يُحدِّد أنّه أي حركة مرور بيانات لا تتوافق مع قاعدة use_backend سيتم تمريرها إلى web-backend، والتي سنقوم بتعريفها في الخطوة القادمة. إعداد الواجهة الخلفية Backend بعد أن تنتهي من إعداد الواجهة الأماميّة، قم الآن إضافة واجهتك الخلفيّة الأولى عن طريق إضافة الأسطر التالية، تأكّد من أن تضع عنوان IP المناسب بدلًا من web_1_private_IP: backend web-backend server web-1 web_1_private_IP:80 check وهذا شرح لما يعنيه كل سطر من المقطع السابق المأخوذ من إعدادات الواجهة الخلفيّة: backend web-backend: يُعيِّن واجهة خلفيّة تُدعى web-backend. server web-1 ... : يُعيِّن خادوم واجهة خلفيّة يُدعى web-1، مع عنوان IP الخاص (وهو الذي يجب أن تستبدله) والمنفذ الذي يستمع عليه، وهو 80 في هذه الحالة، يُخبِر الخيار check مُوازِن الحمل أن يُجري دوريًّا تحقّق من السّلامة على هذا الخادوم. بعدها أضف الواجهة الخلفيّة لتطبيق ووردبريس لديك: backend wordpress-backend reqrep ^([^\ :]*)\ /wordpress/(.*) \1\ /\2 server wordpress-1 wordpress_1_private_IP:80 check وهذا شرح لما يعنيه كل سطر من المقطع السابق المأخوذ من إعدادات الواجهة الخلفيّة: backend wordpress-backend: يُعيِّن واجهة خلفيّة تُدعى wordpress-backend. reqrep ... : يعيد كتابة الطلبات من wordpress/ إلى / عند تمرير حركة مرور البيانات إلى خواديم ووردبريس، وهو ليس ضروريًّا إن كان تطبيق ووردبريس مُثبّتًا على جذر root الخادوم ولكن نحتاج إليه لقابلية النفاذ عبر wordpress/ على خادوم HAProxy. server wordpress-1 ... : يُعيِّن خادوم واجهة خلفيّة يُدعى wordpress-1، مع عنوان IP الخاص (وهو الذي يجب أن تستبدله) والمنفذ الذي يستمع عليه، وهو 80 في هذه الحالة، يُخبِر الخيار check مُوازِن الحمل أن يُجري دوريًّا تحقّق من السّلامة على هذا الخادوم. إعدادات HAProxy: الإحصائيات Stats إن أردت تمكين إحصائيّات HAProxy، والتي قد تكون مفيدة في تحديد كيفيّة تعامل HAProxy مع حركة مرور البيانات الواردة، ستحتاج إلى إضافة الأسطر التالية إلى إعداداتك: listen stats :1936 stats enable stats scope www stats scope web-backend stats scope wordpress-backend stats uri / stats realm Haproxy\ Statistics stats auth user:password وهذا شرح لما تعنيه الأسطر غير البديهيّة من المقطع السابق المأخوذ من إعدادات listen stats: listen stats :1936: يقوم بإعداد صفحة إحصائيّات HAProxy لتكون قابلة للنفاذ على المنفذ 1936 (أي http://haproxy_www_public_IP:1936). stats scope ... : يجمع الإحصائيّات على الواجهة المُحدّدة سواء كانت أماميّة أو خلفيّة. / stats uri: يُعيِّن رابط صفحة الإحصائيّات إلى / . stats realm Haproxy\ Statistics: يقوم بتمكين الإحصائيّات وتعيين اسم الاستيثاق realm Authentication (وهو استيثاق ذو نافذة منبثقة)، يُستخدَم بالترابط مع الخيار stats auth. stats auth haproxy:password: يُعيِّن اعتمادات credentials الاستيثاق لصفحة الإحصائيّات، قم بوضع اسم المستخدم وكلمة السّر الخاصّة بك. الآن قم بالحفظ والإغلاق، عند تشغيل HAProxy تكون صفحة الإحصائيّات متوفّرة عبر الرابط http://haproxy_www_public_ip:1936/ حالما تبدأ خدمة HAProxy لديك، تكون HAProxy جاهزة الآن لتشغيلها ولكن فلنقم بتمكين التسجيل logging أولًا. تمكين تسجيل HAProxy إنّ تمكين التسجيل في HAProxy بسيط جدًّا، قم في البداية بتحرير الملف rsyslog.conf: sudo vi /etc/rsyslog.conf ثم ابحث عن السطرين التاليين وأزل التعليق عنهما لتمكين استقبال UDP syslog، يجب أن تبدو كما يلي عند الفراغ منها: $ModLoad imudp $UDPServerRun 514 $UDPServerAddress 127.0.0.1 الآن أعد تشغيل rsyslog لتمكين الإعدادات الجديدة: sudo service rsyslog restart تم تمكين تسجيل HAProxy الآن، سيتم إنشاء ملف السّجل في المسار var/log/haproxy.log/ بعد أن يتم تشغيل HAProxy. تحديث إعدادات ووردبريس الآن وقد تم تغيير رابط تطبيق ووردبريس فيجب علينا تحديث بعض الإعدادات في ووردبريس. قم بتعديل الملف wp-config.php على أي خادوم ووردبريس، هذا الملف موجود في مكان تثبيت ووردبريس (في هذا الدّرس تم تثبيته على المسار var/www/example.com/ ولكن قد يكون مختلفًا لديك): cd /var/www/example.com; sudo vi wp-config.php ابحث عن السطر الموجود في بداية الملف الذي يحتوي على ('define('DB_NAME', 'wordpress وقم بإضافة الأسطر التالية فوقه مع استبدال http://haproxy_www_public_IP: define('WP_SITEURL', 'http://haproxy_www_public_IP'); define('WP_HOME', 'http://haproxy_www_public_IP'); قم بحفظ وإغلاق الملف، تمّ الآن إعداد روابط ووردبريس لتشير إلى موازن الحمل بدلًا من خادوم ووردبريس الأصلي والتي تلعب دورها عند محاولتك النفاذ إلى لوحة تحكم ووردبريس. تشغيل HAProxy قم بتشغيل HAProxy على الخادوم haproxy-www ليتم تطبيق تغييرات الإعدادات: sudo service haproxy restart إتمام الوسيط العكسي Reverse Proxy أصبحت الآن تطبيقاتنا قابلة للوصول إليها عبر نفس المجال، example.com، عبر الوسيط العكسي للطبقة 7، ولكن لم يتم تطبيق موازنة الحمل عليها بعد، تبدو الآن البيئة لدينا كالمخطط التالي: وفقًا للواجهة الأماميّة التي عرفناها سابقًا، هذا وصف حول كيفيّة تمرير HAProxy لحركة مرور البيانات: http://example.com/wordpress: سيتم إرسال أي طلب يبدأ بـ wordpress/ إلى wordpress-backend (والذي يتكون من الخادوم wordpress-1). http://example.com/: سيتم إرسال أيّة طلبات أخرى إلى web-backend (والذي يتكون من الخادوم web-1). إن كان كل ما تريد فعله هو استضافة تطبيقات متعدّدة على مجال وحيد فقد أنجزت هذا بنجاح، أمّا إن أردت موازنة حمل تطبيقاتك أكمل قراءة الدّرس. كيفية إضافة موازنة الحمل موازنة حمل الخادوم web-1 لموازنة حمل خادوم ويب أساسي، كل ما تحتاج إليه هو إنشاء خادوم ويب جديد يمتلك إعدادات ومحتوى مطابق لخادوم الأصلي، سندعو هذا الخادوم الجديد: web-2. لديك خياران عند إنشاء الخادوم الجديد: إن كنت تملك خيار إنشاء خادوم جديد انطلاقًا من صورة web-1، فهذه هي الطريقة الأبسط لإنشاء web-2. إنشاؤه من الصفر، تثبيت نفس البرمجيّات، إعداده بشكل مماثل، ومن ثمّ نسخ محتوى جذر خادوم Nginx من web-1 إلى web-2 باستخدام rsync (اقرأ درس كيف تستخدِم Rsync لمزامنة مجلّدات بين الجهاز المحلّي والخادوم). ملاحظة: إن كل من الطريقتين السابقتين تقوم بإنشاء نسخة لمحتويات جذر الخادوم مرّة وحيدة، لذلك إن قمت بتحديث أي من الملفّات على أحد خواديمك، web-1 أو web-2، فتأكّد من مزامنة الملفّات مرّة أخرى. بعد أن يتم إعداد خادوم ويب المماثل لديك، قم بإضافته إلى web-backend ضمن إعدادات HAProxy. على الخادوم haproxy-www قم بتحرير الملف haproxy.cfg: sudo vi /etc/haproxy/haproxy.cfg ابحث عن القسم web-backend من الإعدادات: backend web-backend server web-1 web_1_private_IP:80 check وبعدها أضف الخادوم web-2 في السطر التالي: server web-2 web_2_private_IP:80 check قم بحفظ وإغلاق الملف، وأعد تحميل HAProxy لتطبيق التغييرات: sudo service haproxy reload يمتلك web-backend الآن خادومين يتعاملان مع حركة مرور البيانات غير المرتبطة بووردبريس، أي تمّ إعداد موازنة الحمل عليه بنجاح. موازنة حمل الخادوم wordpress-1 إنّ موازنة حمل تطبيق مثل ووردبريس أكثر تعقيدًا بقليل من موازنة حمل خادوم ثابت، لأنّه يجب عليك الاهتمام بأشياء مثل مزامنة الملفّات المُحمّلة ومستخدمي قواعد البيانات الإضافيّين. أكمل الخطوات الثلاث التالية لإنشاء خادوم ووردبريس الثاني wordpress-2: إنشاء خادوم تطبيق ويب الثاني. مزامنة ملفّات تطبيق الويب. إنشاء مستخدم قاعدة بيانات جديد. بعد أن تقوم بإنشاء الخادوم wordpress-2 مع إعداد قاعدة البيانات بشكل صحيح فكل ما تبقى عليك فعله هو إضافته إلى wordpress-backend ضمن إعدادات HAProxy. على الخادوم haproxy-www قم بتحرير الملف haproxy.cfg: sudo vi /etc/haproxy/haproxy.cfg ابحث عن القسم wordpress-backend من الإعدادات: backend wordpress-backend server wordpress-1 wordpress_1_private_IP:80 check وبعدها أضف الخادوم wordpress-2 في السطر التالي: server wordpress-2 wordpress_2_private_IP:80 check قم بحفظ وإغلاق الملف، وأعد تحميل HAProxy لتطبيق التغييرات: sudo service haproxy reload يمتلك web-backend الآن خادومين يتعاملان مع حركة مرور البيانات غير المرتبطة بووردبريس، أي تمّ إعداد موازنة الحمل عليه بنجاح. الخاتمة بعد أن أتممت الآن هذا الدّرس يجب أن تكون قادرًا على توسيع موازنة الحمل والوسيط العكسي لإضافة المزيد من التطبيقات والخواديم لبيئتك لجعلها تتوافق بشكل أفضل مع احتياجاتك، تذكّر أنّه لا توجد حدود لطرق إعداد بيئتك، وربّما تحتاج إلى البحث في توثيق HAProxy إن أردت متطلبات أكثر تعقيدًا. ترجمة -وبتصرّف- للمقال How To Use HAProxy As A Layer 7 Load Balancer For WordPress and Nginx On Ubuntu 14.04 لصاحبه Mitchell Anicas.
-
إن Squid هو خادوم تخزين وسيط للويب (web proxy cache server) الذي يوفر خدمات الوساطة والتخزين لبروتوكول نقل النص الفائق (HTTP)، وبروتوكول نقل الملفات (FTP)، وغيرهما من بروتوكولات الشبكة الشهيرة؛ يمكن أن يدعم Squid التخزين والوساطة لطلبات طبقة المقابس الآمنة (SSL) وتخزين طلبيات DNS؛ ويدعم Squid أيضًا بروتوكولات تخزين مخبأ مختلفة، مثل بروتوكول تخزين الإنترنت (Internet Cache Protocol اختصارًا ICP)، وبروتوكول تخزين النص الفائق (Hyper Text Caching Protocol اختصارًا HTCP)، وبروتوكول تخزين مصفوفة التوجيه (Cache Array Routing Protocol اختصارًا CARP)، وبروتوكول تنسيق تخزين الويب (Web Cache Coordination Protocol اختصارًا WCCP). إن الخادوم الوسيط Squid هو حل ممتاز لاحتياجاتٍ كثيرةً للوساطة أو التخزين المؤقت، والتوسع من مكتب فرعي إلى شبكة الشركة الكبيرة وذلك بتوفير آليات مراقبة وتحكم في الوصول للمعاملات المهمة باستخدام بروتوكول إدارة الشبكة المبسط (Simple Network Management Protocol اختصارًا SNMP). عند اختيار حاسوب ليعمل كخادوم Squid، فتأكد أنه مضبوط مع كمية كبيرة من الذاكرة الفيزيائية، حيث يستخدم Squid التخزين في الذاكرة لزيادة الأداء. التثبيتأدخِل الأمر الآتي في الطرفية لتثبيت خادوم Squid: sudo apt-get install squid3الضبطيُضبَط Squid بتعديل التعليمات الموجودة ضمن ملف الضبط /etc/squid3/squid.conf؛ الأمثلة الآتية تعرض بعض التعليمات التي يمكن تعديلها لتغيير سلوك خادوم Squid؛ للمزيد من التفاصيل المعمَّقة حول Squid، فانظر إلى قسم المصادر. تنويه: قبل تعديل ملف الضبط، تأكد أنك ستُنشِئ نسخةً من الملف الأصلي وتحميها من الكتابة كي تحصل على الإعدادات الافتراضية كمرجعٍ لك، أو أن تعيد استخدامها وقت الحاجة. انسخ الملف /etc/squid/squid.conf واحمهِ من الكتابة بإدخال الأوامر الآتية في الطرفية: sudo cp /etc/squid3/squid.conf /etc/squid3/squid.conf.original sudo chmod a-w /etc/squid3/squid.conf.originalلضبط خادوم Squid لكي يستمع إلى منفذ TCP ذو الرقم 8888 بدلًا من منفذ TCP الافتراضي 3128، فعدِّل التعليمة http_port كما يلي: http_port 8888عدِّل التعليمة visible_hostname لكي تعطي خادوم Squid اسم مضيف خاص به؛ هذا الاسم لا يفترض أن يكون نفس اسم المضيف للحاسوب؛ ضُبِطَ في هذا المثال إلى weezie: visible_hostname weezieباستخدام التحكم في الوصول الخاص بخادوم Squid، ربما تضبط استخدام خدمات الإنترنت التي يكون فيها Squid وسيطًا لتتوفر للمستخدمين الذي يملكون عناوين IP معيّنة؛ ففي هذا المثال، سنسمح بالوصول لمستخدمي الشبكة الفرعية 192.168.42.0/24 فقط: أضف ما يلي إلى نهاية قسم ACL من ملف ضبط /etc/squid3/squid.conf: acl fortytwo_network src 192.168.42.0/24ثم أضف ما يلي إلى بداية قسم http_access في ملف /etc/squid3/squid.conf: http_access allow fortytwo_networkباستخدام ميزات التحكم بالوصول الممتازة التي يوفرها Squid؛ فربما تضبط استخدام خدمات الإنترنت التي يكون فيها Squid وسيطًا كي تتوفر فقط أثناء ساعات العمل العادية؛ على سبيل المثال، سنحاكي وصول الموظفين خلال ساعات العمل من 9:00AM إلى 5:00PM ومن الاثنين إلى الجمعة، الذين يستخدمون الشبكة الفرعية 10.1.42.0/42: أضف ما يلي إلى نهاية قسم ACL في ملف /etc/squid3/squid.conf: acl biz_network src 10.1.42.0/24 acl biz_hours time M T W T F 9:00-17:00ثم أضف ما يلي إلى أعلى قسم http_access في ملف /etc/squid3/squid.conf: http_access allow biz_network biz_hoursملاحظة: بعد عمل تغيرات إلى ملف الضبط /etc/squid3/squid.conf، فاحفظ الملف ثم أعد تشغيل خادوم Squid لكي تأخذ التغيرات مجراها بإدخال الأمر الآتي في الطرفية: sudo service squid3 restartمصادرموقع Squid.صفحة ويكي أوبنتو «Squid».ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Squid - Proxy Server.
-
لقد أصبح Nginx أحد أكثر التطبيقات البرمجية المتوفرة لخواديم الويب Web Servers مرونةً وقوة. ولكن إذا ما نظرنا إليه من الناحية التصميمية فإنه يعد أولًا وقبل كل شيء خادومًا وسيطا Proxy Server. إن التركيز على أداء Nginx كوسيط يعني أنه ذو أداء عالي عندما يعمل على معالجة الطلبات بالتعاون مع خواديم أخرى. يمكن لـ Nginx أن يلعب دور الوسيط باستخدام بروتوكولات Protocols http ,FastCGI ,uwsgi ,SCGI ,memcached. سنناقش في هذه المقالة استخدام FastCGI للقيام بالوساطة proxying، فهو يعد واحدًا من أكثر البرتوكولات التي تُستخدم لذلك الغرض. لماذا نستخدم FastCGI للقيام بالوساطة؟يستخدم FastCGI للقيام بالوساطة ضمن Nginx كي يترجم طلبات المستخدمين Clients لخادوم التطبيقات Application Server الذي لا يقوم بمعالجة طلبات المستخدمين مباشرةً أو الذي لا ينبغي له ذلك. إنّ FastCGI هو برتوكول مبني على برتوكول Common Gateway Interface الأقدم والذي يشار إليه اختصارًا CGI، وقد أُريد من بروتوكول FastCGI أن يحسّن أداء البروتوكول السابق عبر عدم معالجة كل طلب في عملية Process خاصة به. يُستخدم البرتوكول ليمثّل واجهة interface ذات فعالية أكبر مع الخواديم التي تعالج طلبات المحتوى الديناميكي. إن معالجة PHP هي أحد حالات الاستخدام use-case الرئيسية لبرتوكول FastCGI ضمن Nginx. وعلى عكس أباتشي Apache، الذي يستطيع معالجة PHP مباشرةً باستخدام وحدة mod_php، فإنه ينبغي على Nginx الاعتماد على معالج PHP منفصل لمعالجة طلبات PHP. غالبًا ما تُنجز تلك المعالجة باستخدام php_fpm وهو معالج PHP قد اختبر بشكل كبير للعمل مع Nginx. يمكن أن يُستخدم Nginx مع FastCGI للعمل مع تطبيقات تستخدم لغاتٍ أخرى طالما أنه يتوفر مكونات مهيّأة للاستجابة لطلبات FastCGI. أسياسيات قيام FastCGI بالوساطةعادةً ما تتضمن طلبات الوساطة proxying requests عنوان الخادوم الوسيط- Nginx في حالتنا- الذي يوجّه الطلبات من قبل المستخدمين إلى الخادوم الوسيط بينه (الخلفي) Backend Server. يستخدم Nginx التعليمة fastcgi_pass للتعريف عن الخادوم الفعلي الذي ستوجّه إليه الطلبات باستخدام برتوكول FastCGI. فمثلًا، لتوجيه أي طلب موافق للغة PHP إلى الخادوم الخلفي المخصص لمعالجة PHP باستخدام برتوكول FastCGI، فقد يبدو المقطع البرمجي للموقع Location Block مشابهًا لما يلي: # server context location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; } . . . في الواقع، لن يعمل المقطع السابق إذا ما تم تنفيذه على حاله لأنه يقدّم معلوماتٍ قليلةً جدًا. في كل مرّة يتم فيها إنشاء اتصال وسيط Proxy Connection فإنه يجب ترجمة الطلب الأصلي لضمان أن يتمكن الخادوم الخلفي من فهم الطلب المُدار Proxied request. وباعتبار أننا نغيّر البرتوكولات بتمرير الطلب عبر FastCGI فإن ذلك يتطلب بعض العمل الإضافي، سنصطلح في هذه المقالة على عملية تمرير الطلبات عبر FastCGI بتمرير FastCGI أي FastCGI pass. إنّ القيام بالوساطة من بروتوكول Http وإليه http-to-http Proxying ينطوي بشكل رئيسي على زيادة حجم الترويسة Header ليضمن أن يمتلك الخادوم الخلفي المعلومات التي يحتاجها للرد على الخادوم الوسيط والذي ينوب بدوره عن المستخدم Client، أما FastCGI فهو برتوكول منفصل لا يستطيع قراءة ترويسات Http. مع أخذ ذلك بالحسبان فإن أية معلومات ذات صلة يجب أن تمرّر للخادوم الخلفي عبر وسيلة أخرى. إن الطريقة الأساسية لتمرير المعلومات الإضافية عند استخدام برتوكول FastCGI هي باستخدام الإعدادات Parameters. حيث يجب أن يُهيّئ الخادوم الخلفي لقراءة تلك الإعدادات ومعالجتها والتصرّف وفقًا لقيمها. يستطيع Nginx أن يحدّد إعدادات FastCGI باستخدام التعليمة fastcgi_param. إن الحد الأدنى للإعدادات الواجب ضبطها حتى يعمل FastCGI كوكيل PHP مشابهة لما يلي: # server context location ~ \.php$ { fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000; } . . . لقد قمنا في الإعدادات السابقة بضبط إعدادات FastCGI وهما REQUEST_METHOD و SCRIPT_FILENAME. إن كل من الإعدادات السابقة ضرورية للخادوم الخلفي حتى يتمكن من فهم طبيعة الطلب. إذ أن الإعداد الأول يخبره بنوع العملية التي يجب أن يقوم بإنجازها، أما الإعداد الثاني فيخبر مجموعة الخواديم Upstream - التي تعالج طلبات الخادوم الوسيط- بالملف الذي يجب أن ينفّذه. استخدمنا في المثال بعض المتغيرات variables في Nginx لضبط قيم تلك الإعدادات. سيحوي المتغير request_method$ على نوع الوظيفة http method التي طلبها المستخدم. من ناحية أخرى فإن قيمة الإعداد SCRIPT_FILENAME هي عبارة عن دمج قيمتي المتغيرين document_root$ و fastcgi_script_name$. أما المتغير document_root$ فسيحوي على مسار المجلد الرئيسي والذي ضبط عبر التعليمة root. سيضبط المتغير fastcgi_script_name$ بمعرف الموارد الموحد URI المطلوب. إن انتهى معرف URI للطلب request URI بالرمز (/)، فستلحق قيمة التعليمة fastcgi_index في النهاية. إن هذا النوع من المرجعية الذاتية self-referential في تعريف الموقع ممكن لأننا نشغّل معالج FastCGI على نفس الجهاز الذي يشغّل Nginx. فلنلقي نظرة على مثال آخر: # server context root /var/www/html; location /scripts { fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; fastcgi_pass unix:/var/run/php5-fpm.sock; } . . .إن اختير الموقع location في المثال السابق ليعالج طلبًا في المسار: /scripts/test/ فإن قيمة المسار الوسيط SCRIPT_FILENAME ستنتج عن دمج قيم تعليمة root ومعرّف URI للطلب بالإضافة للتعليمة fastcgi_index. وبالتالي ستكون قيمة الإعداد في مثالنا هذا هي: var/www/html/scripts/test/index.php/ هنالك تعديل هام آخر قمنا به في الإعدادات السابقة، إذ أننا ضبطنا خادوم FastCGI الخلفي FastCGI backend ليستخدم مقبس يونيكس Unix Socket عوضًا عن مقبس شبكة Network socket. يمكن لـ Nginx أن يستخدم أيًا من الواجهتين Interface ليتصل مع مجموعة خواديم FastCGI Upstream. إن كان معالج FastCGI يعمل على نفس الخادوم فعادةً ما يُستحسن استخدام مقبس يونيكس من أجل الأمان. شرح إعدادات FastCGIهنالك قاعدة أساسية لكتابة نص برمجي (كود) Code قابل للصيانة وهي محاولة اتباع مبدأ DRY أي لا تكرر نفسك "Don’t Repeat Yourself". يساعد ذلك في تقليل الأخطاء بالإضافة لجعل الكود قابلًا لإعادة الاستخدام كما أنها تتيح تنظيمًا أفضل. إنّ أحد أكثر التوصيات الأساسية لإدارة Nginx هي أن تُضبط كل الأوامر في أوسع مجال ممكن لها، تطبّق تلك الأهداف الأساسية على إعداداتNginx أيضًا. عند التعامل مع إعدادات الوسيط لـ FastCGI فسيتم تشارك الغالبية العظمى للإعدادات في معظم حالات الاستخدام. بسبب ذلك وبسبب الطريقة التي تعمل بها وحدة الوراثة inheritance التابعة لـ Nginx فإنه دائمًا ما يستحسن تعريف الوسطاء في مجال عام. التصريح عن تفاصيل إعدادات FastCGI في السياقات الأم Parent Contextsإن أحد الطرق لتقليل التكرار هو التصريح عن تفاصيل الإعدادات في السياق الأم، أي سياق أعلى. يمكن لكل الإعدادات الموجودة خارج التعليمة fastcgi_pass أن تُضبط في مستويات أعلى. إذ أنها ستتدفق للأسفل نحو الموقع الذي تم منه تمرير الإعداد. وذلك يعني أنّه يمكن لعدّة أماكن أن تستخدم نفس الإعدادات. فمثلًا، يمكننا أن نعدّل على القسم العلوي من المقطع البرمجي السابق لجعله مفيدًا في عدة مواقع: # server context root /var/www/html; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; location /scripts { fastcgi_pass unix:/var/run/php5-fpm.sock; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; } . . .إنّ كلًا من تصاريح fastcgi_param والتعليمة fastcgi_index في المثال السابق متوفرين لدى مقطعي الموقع location block الواردين لاحقًا. تلك هي إحدى الطرق لإزالة التكرار. بكل الأحوال، إن للإعدادات السابقة مساوئ كبيرة، إن صُرّح عن أية fastcgi_param ضمن سياق أدنى فلن تتم وراثة أيٍّ من قيم fastcgi_param ضمن السياقات العليا (السياقات الأم). أي إما أن تستخدم القيم الموروثة فقط أو لا تستخدم أيًا منها. تُعد التعليمة fastcgi_param مصفوفةً array من التعليمات في لغةNginx. من منظور المستخدمين فإن أي مصفوفة تعليمات هي بشكل أساسي تعليمة يمكن استخدامها أكثر من مرة ضمن سياق واحد. وأي تصريح لاحق سيضيف معلومات جديدة إلى ما يعرفه Nginx من التصريح السابق. لقد صمّمت التعليمة fastcgi_param كمصفوفة من التعليمات حتى تسمح للمستخدمين بضبط عدّة إعدادات. تورّث أي مصفوفة تعليمات إلى سياق أدنى، أو سياق ابن child context، بطريقة مختلفة عن بعض التعليمات الأخرى. ستورّث معلومات مصفوفة التعليمات إلى سياقات الأبناء فقط إن لم تكن موجودة في أي مكان ضمن سياق الابن. وذلك يعني أنك إن استخدمت تعليمة fastcgi_param ضمن موقعك فإنها ستمحي القيم الموروثة من السياق الأعلى تمامًا. فمثلًا، يمكننا التعديل قليلًا على الإعدادات السابقة كما يلي: # server context root /var/www/html; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; location /scripts { fastcgi_pass unix:/var/run/php5-fpm.sock; } location ~ \.php$ { fastcgi_param QUERY_STRING $query_string; fastcgi_pass 127.0.0.1:9000; } . . .قد تعتقد للوهلة الأولى أنه ستتم وراثة الإعدادات REQUEST_METHOD و SCRIPT_FILENAME في مقطع لموقع ثانٍ، بالإضافة لتوفير الإعداد QUERY_STRING ضمن ذلك السياق المحدّد. لكن ما يحدث في الحقيقة هو أنّ كل قيم fastcgi_param التابعة للأب ستُمحى ضمن السياق الثاني، وسيضبط الإعداد QUERY_STRING فقط. بينما ستبقى الإعدادات REQUEST_METHOD و SCRIPT_FILE دون ضبط. ملاحظة حول القيم المتعدّدة للوسطاء ضمن نفس السياقيجدر بالذكر هنا أثار ضبط قيم متعدّدة لنفس الإعدادات ضمن سياق واحد. فلنأخذ المثال التالي لمناقشة ذلك: # server context location ~ \.php$ { fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $request_uri; fastcgi_param DOCUMENT_ROOT initial; fastcgi_param DOCUMENT_ROOT override; fastcgi_param TEST one; fastcgi_param TEST two; fastcgi_param TEST three; fastcgi_pass 127.0.0.1:9000; } . . .في المثال السابق، قمنا بضبط الإعدادات TEST و DOCUMENT_ROOT عدّة مرات ضمن سياقٍ واحد. باعتبار أن fastcgi_param مصفوفة تعليمات فإن كلّ تصريح لاحق سيُضاف إلى سجلات Nginx الداخلية. سيحظى الإعداد TEST بعدة تصاريح ضمن المصفوفة يضبط من خلالها بالقيم one و two و three. من المهم أن ندرك هنا أنّ كلّ ذلك سيمرّر إلى خادوم FastCGI الخلفي دون أي معالجة إضافية من Nginx. يعني ذلك أنّ القرار حول كيفية معالجة تلك القيم يعود بشكل كامل إلى معالج Nginx المختار. للأسف، على اختلاف معالجات FastCGI فإن كلًا منها يعالج القيم الممرّرة بطريقة تختلف تمامًا عن الأخرى. فمثلًا، إن استقبلت PHP-FPM الإعدادات السابقة فستفسر القيم النهائية لتحل محل أي قيم سابقة. بهذه الحالة سيُضبط الإعداد TEST بالقيمة three. وبالمثل سيضبط الإعداد DOCUMENT_ROOT بالقيمة override. ولكن إن مُرّرت القيم السابقة لخادومٍ مثل FsgiWrap، فستفسَّر القيم بشكل مختلف كثيرًا. ففي البداية سيقوم بتمرير تمهيدي ليقرر أي القيم ينبغي استخدامها لتشغيل البريمج script. وسيستخدم القيمة initial للإعداد DOCUMENT_ROOT ليبحث عن البريمج. إلا أنه عندما سيمرّر القيم الفعلية للبريمج فسيمرر القيم الأخيرة كما يفعل PHP-FPM تمامًا. إن التضارب inconsistency وعدم إمكانية التنبؤ unpredictability يعني أنك لا تستطيع، بل أنه لا ينبغي لك، أن تعتمد على الخادوم الخلفي لتفسير نيّتك بشكل صحيح إذا ما ضبطّت الإعدادات أكثر من مرّة واحدة. فالطريقة الوحيدة الآمنة هي بالتصريح عن كل إعداد مرّةً واحدة. يعني ذلك أيضًا أنه لا يوجد طريقة آمنة لإعادة تعريف overriding القيمة الافتراضية باستخدام تعليمة fastcgi_param. طريقة تضمين إعدادات مكتوبة بملف منفصل ضمن ملف إعدادات FastCGI الأساسييوجد طريقة أخرى لتفصل بنود إعداداتك الشائعة، أي التي تقوم بها بشكل متكرّر. بإمكاننا استخدام تعليمة include لقراءة محتوى ملف منفصل وتضمينها في الموقع الذي تم فيه التصريح عن التعليمة. يعني ذلك أنه بإمكاننا الاحتفاظ بكل الإعدادات الشائعة في ملف واحد ومن ثمّ تضمينه في أي مكان ضمن إعداداتنا إن اقتضى الأمر. وباعتبار أن Nginx سيضع محتوى الملف حيثما وجدت تعليمة include فلن نكون قد ورثنا من سياق الأم إلى سياق الابن. سيمنع ذلك قيم fastcgi_param من أن تُمحى وسيمنحنا القدرة على ضبط إعدادات إضافية عند الحاجة. يمكننا في البداية أن نضبط قيم إعدادات FastCGI الشائعة لدينا في ملف منفصل وتخزينه ضمن المسار الحاوي على ملف الإعدادات الأصلي، سنقوم بتسمية ذلك الملف fastcgi_common: fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;يمكننا الآن أن نستورد محتوى الملف حيثما نريد استخدام قيم تلك الإعدادات: # server context root /var/www/html; location /scripts { include fastcgi_common; fastcgi_index index.php; fastcgi_pass unix:/var/run/php5-fpm.sock; } location ~ \.php$ { include fastcgi_common; fastcgi_param QUERY_STRING $query_string; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; } . . . لقد قمنا هنا بنقل قيم بعض الإعدادات الشائعة إلى ملف اسمه fastcgi_common والموجود في المسار الافتراضي الحاوي على إعدادات NGINX. ثمّ نستورد القيم المصرّح عنها في الملف عندما نحتاج لإدخالها. هنالك العديد من الأمور التي يجب ملاحظتها حول هذه الإعدادات: أولًا، لم نضع في الملف الذي ننوي استيراده أي قيم قد نرغب بتخصيصها وفقًا لموقعه، بسبب مشكلة التفسير التي ذكرناها سابقًا والتي تحدث عندما نضبط عدة قيم لنفس الإعداد، ولأنه لا يمكن ضبط التعليمات التي ليست على شكل مصفوفة non-array directives إلا مرّةً واحدة خلال السياق، لذا نضع العناصر التي لن نرغب بتغييرها فقط في الملف المشترك. إنّ كلّ تعليمة (أو إعداد أساسي) قد نرغب بتخصيصه وفقًا لموقعه يجب ألا يضمّن في الملف المشترك. الأمر الآخر الذي ربما قد لاحظته أننا قد ضبطنا بعض إعدادات FastCGI الإضافية في المقطع البرمجي للموقع الثاني. وتلك هي الإمكانية التي كنا نأمل الوصول إليها. تمكّنا من إضافة إعدادات fastcgi_param إضافية كلما اقتضت الحاجة ومن دون أن تُمسح القيم المشتركة. استخدام الملف fastcgi_params أو الملف fastcgi.confبأخذ الاستراتيجية السابقة بالحسبان فإن مطوري Nginx والعديد من فرق تحزيم التوزيعات distribution packaging teams قد عملوا على توفير مجموعة من الإعدادات شائعة الاستخدام والتي يمكن أن تضمنها في مواقع تمرير FastCGI أي FastCGI pass location. تدعى تلك الإعدادات fastcgi_params أو fastcgi.conf. إنّ هذين الملفين متشابهين كثيرًا ولكن مع وجود اختلاف وحيد ممثّل في تمرير قيم متعدّدة لإعداد واحد، وهي المشكلة التي ناقشناها سابقًا، لا يحتوي fastcgi_params على تصريح عن الإعداد SCRIPT_FILENAME على عكس الملف fastcgi.conf. لقد أوجِد الملف fastcgi_params منذ وقتٍ أبعد. ثم ظهرت الحاجة لإنشاء ملف جديد عندما اتُّخذ قرارٌ لتوفير قيمةٍ افتراضية للإعداد SCRIPT_FILENAME وذلك حتى نتجنب تجزئة الإعدادات التي تعتمد على fastcgi_params، إن عدم فعل ذلك قد يؤدي إلى ضبط ذلك الإعداد في كل من الملف المشترك وموقع تمرير FastCGI. العديد من مشرفي تحزيم التوزيعات الشهيرة قد صوّتوا لتضمين إحدى هذين الملفين فقط أو لتطابق محتواهما تمامًا. إن توفّر لديك أحد هذين الملفين فقط فاستخدمه وعدّل عليه كما تشاء ليناسب احتياجاتك. إن كان كلا الملفين متوفرين لك، فقد يكون من الأفضل أن تضمّن الملف fastcgi.conf في معظم مواقع تمرير FastCGI، وذلك لأنه يتضمّن تصريحًا عن الإعداد SCRIPT_FILENAME. عادةً ما يُرغب بذلك إلا أنّ هنالك بعض الحالات التي قد ترغب فيها بتخصص هذه القيمة. يمكن تضمين هذين الملفين عبر الإشارة إلى موقعهما بالنسبة إلى المجلد الجذر root الحاوي على إعدادات Nginx. إن مسار المجلد الجذر لإعداداتNginx يكون مشابهًا لما يلي: etc/nginx/ وذلك إن تم تثبيته باستخدام مدير الحزم package manager. يمكنك تضمين الملفين كما يلي: # server context location ~ \.php$ { include fastcgi_params; # You would use "fastcgi_param SCRIPT_FILENAME . . ." here afterwards . . . }أو كما يلي: # server context location ~ \.php$ { include fastcgi.conf; . . . }تعليمات وإعدادات ومتغيرات FastCGI المهمّةلقد قمنا في القسم السابق بضبط عدد لا بأس به من الإعدادات بهدف شرح مفاهيمٍ أخرى، وعادةً ما كنا نضبطها بمتغيرات Nginx. كما أننا قدمنا بعض تعليمات FastCGI من دون شرحٍ وفير. سنناقش في هذا القسم بعض التعليمات شائعة الضبط، وبعض الإعدادات التي قد تحتاج لتعديلها، بالإضافة لبعض المتغيرات التي قد تحوي معلوماتٍ تحتاجها. تعليمات FastCGI الشائعة:سنستعرض فيما يلي بعض أكثر التعليمات المفيدة للعمل مع تمريرات FastCGI: fastcgi_pass: هي التعليمة التي تقوم بعملية تمرير الطلبات الموجودة ضمن السياق الحالي إلى الخادوم الخلفي. تعرٍّف هذه التعليمة الموقع الذي يمكن الوصول عبره إلى معالج FastCGI.fastcgi_param: وهي مصفوفة التعليمات التي يمكن استخدامها لضبط قيم الإعدادات. غالبًا ما يقترن استخدام هذه التعليمة مع متغيرات Nginx لضبط وسطاء FastCGI بالقيم المحدّدة في الطلب.try_files: ليست تعليمةً خاصة بـ FastCGI، إلا أنها استخدامها شائع في موقع تمرير FastCGI، عادةً ما تستخدم كجزء من إجراء الطلب الوقائي للتأكد من وجود الملف المطلوب قبل تمريره إلى معالج FastCGI.include: مجدّدًا، ليست تعليمةً خاصة بـ FastCGI، إلا أنها تستخدم بكثافة عالية في سياقات تمرير FastCGI أي FastCGI pass contexts. غالبًا ما تستخدم لتضمين تفاصيل الإعدادات الشائعة والمشتركة بين عدّة مواقع.fastcgi_split_path_info: تستخدم هذه التعليمة لتعريف التعابير النمطية regular expression مع مجموعتي التقاط captured groups. تُستخدم المجموعة الأولى كقيمة للمتغير fastcgi_script_name$ بينما تستخدم المجموعة الثانية كقيمة للمتغير fastcgi_path_info$. عادةً ما تستخدم كلا المجموعتين لتحليل parse الطلب بشكل صحيح حتى يعرف المعالج أي الأجزاء المشكّلة للطلب تمثل الملفات الواجب تشغيلها وأي الأجزاء تمثل المعلومات الإضافية الواجب تمريرها إلى السكربت.fastcgi_index: تعرّف هذه التعليمة ملف الفهرسة index file الذي ينبغي الحاقه بقيمة الإعداد fastcgi_script_name$ والتي تنتهي بـ (/.عادةً ما يكون ذلك مفيدًا إن كان الإعداد SCRIPT_FILENAME مضبوطًا بقيمة document_root$fastcgi_script_name$ وكان مقطع الموقع معدّا لقبول الطلبات الحاوية على معلومات المسار الإضافية.fastcgi_intercept_errors: تعرّف هذه التعليمة فيما إذا كان ينبغي معالجة الأخطاء المتلقاة من خادوم FastCGI أو تمريرها مباشرةً إلى المستخدم.تمثّل التعليمات السابقة أكثر التعليمات التي ستستخدمها عندما تصمّم تمرير FastCGI نموذجي. ومع أنك قد لا تستخدمها كلها بنفس الوقت، إلا أنك ستلاحظ أنها تتفاعل بشكل وثيق جدًا مع إعدادات ومتغيرات FastCGI التي سنتحدث عنها فيما يلي. المتغيرات شائعة الاستخدام مع FastCGI:قبل أن نتمكن من الكلام عن الإعدادات التي ستستخدمها على الأرجح مع تمريرات FastCGI، علينا الكلام قليلًا عن بعض نتغيرات Nginx الشائعة والتي ستستفيد منها في ضبط تلك الإعدادات. تعرّف وحدة FastCGI الخاصة بـ Nginx بـ Nginx’s FastCGI module بعض تلك المتغيرات، إلا أن معظمها من الوحدة الأساسية Core module. query_string$ أو args$: هي القيم الممرّرة arguments في الطلب الأصلي للمستخدم. is_args$: ستساوي قيمتها “?” إن حوى الطلب على قيم ممرّرة وإلا فستُضبط قيمتها بسلسلة نصية فارغة. يفيد ذلك عند إنشاء إعدادات قد تأخذ قيمًا أو لا تأخذ. request_method$: يشير هذا المتغير إلى نوع الطلب request method المستخدم الأصلي. يمكن أن يفيد ذلك بتحديد فيما إذا كان ينبغي السماح لعملية operation ما في السياق الحالي أم لا. content_type$: يضبط هذا المتغير بقيمة الحقل content-type الموجود في ترويسة الطلب. يحتاج الوسيط إلى هذه المعلومات إن كان نوع الطلب المستخدم هو POST وذلك حتى يتمكن من معالجة المحتويات اللاحقة بشكل صحيح. content_length$: يضبط هذا المتغير قيمة الحقل Content-Length الموجود في ترويسة المستخدم. هذه المعلومات لازمة لأي طلب للمستخدم من النوع POST. fastcgi_script_name$: يحتوي هذا المتغير على ملف السكربت الذي يجب تشغيله. إن انتهى الطلب بـ (/) فستحلق قيمة التعليمة fastcgi_index إلى النهاية. وبحال استخدام التعليمة fast_split_path_info فستضبط قيمة هذا المتحول بالمجموعة اللاقطة الأولى المعرّفة من قبل التعليمة. ينبغي على قيمة هذا المتغير أن تشير إلى الملف الفعلي الذي يجب تشغيله. request_filename$: يحتوي هذا المتغير على مسار الملف المطلوب. يحصل المتغير على هذه القيمة بأخذ المسار الحالي لمجلد المستندات الأساسي document root، مع أخذ كل من التعليمتين root و alias بعين الاعتبار. بالإضافة لأخذ قيمة المتغير fastcgi_script_name$. تعد هذه الطريقة مرنةً للغاية لإسناد قيمة للإعداد SCRIPT_FILENAME. request_uri$: يحتوي هذا المتغير على الطلب كاملًا كما استُقبل من المستخدم، يتضمّن ذلك السكربت، أية معلومات مسار إضافية، بالإضافة إلى أي عبارة استعلام query string. fastcgi_path_info$: يحتوي هذا المتغير على معلومات المسار الإضافية التي قد تتوفّر بعد اسم السكربت في الطلب. وقد تحوي قيمته أحيانًا على موقعٍ آخر ينبغي على السكربت أن يعلم به حتى يتم تنفيذه. يحصل هذا المتغير على قيمته من مجموعة التعابير النمطية regex الثانية عند استخدام تعليمة fastcgi_split_path_info. document_root$: يحتوي هذا المتغير على المسار الحالي لمجلد المستندات الأساسي. وسيتم ضبطه تبعًا لتعليمتي root و alias. uri$: يحتوي هذا المتغير على قيمة URI الحالية بعد تسويتها normalization. وبما أن تعليمات معينة تقوم بإعادة الكتابة rewrite أو بإعادة التوجيه الداخلي internallly redirect يمكن أن تترك أثرًا على معرّف URI فإن هذا المتغير سيستخلّص تلك التعديلات. كما ترى، يوجد العديد من المتغيرات المتوفّرة لك عندما تقرّر كيف تضبط إعدادات FastCGI. العديد منها متشابه إلا أنها تملك بعض الفوارق الصغيرة والتي ستنعكس على تنفيذ بريمجك. إعدادات FastCGI الشائعة:تمثّل إعدادات FastCGI المعلومات التي نرغب بجعلها متاحةً لمعالج FastCGI - الذي نرسل إليه الطلبات- على شكل أزواج مفتاح-قيمة key-value. لن تحتاج كلّ التطبيقات إلى نفس الإعدادات لذلك غالبًا ما ستحتاج لمراجعة توثيق التطبيق. تُعد بعض تلك الإعدادات ضروريةً للمعالج حتى يتمكن من تحديد السكربت - الذي ينبغي تشغيله- بشكل صحيح. بينما أُتيح البعض الآخر للسكربت، إذ أنها قد تغيّر سلوكه إن كان معدًّا ليعتمد على مجموعةٍ من الإعدادات. QUERY_STRING: ينبغي أن يُضبط هذا الإعداد بأي عبارة استعلام مقدّمة من قِبل المستخدم. عادةً ما تكون على شكل أزواج مفتاح-قيمة مزوّدةً بعد إشارة "?" في معرّف URI. عادةً ما يُضبط هذا الإعداد بقيمة أحد المتحولين query_string$ أو args$، إذ ينبغي عليهما أن يحويا على نفس البيانات. REQUEST_METHOD: يدّل هذا الإعداد معالجَ FastCGI على نوع الإجراء الذي طلبه المستخدم. وهو أحد الإعدادات القلائل التي يجب ضبطها حتى يتم التمرير بشكل صحيح. CONTENT_TYPE: إن ضُبط نوع الطلب في الإعداد السابق ليكون POST فيجب أن يُضبط هذا الإعداد. يشير هذا الإعداد إلى نوع البيانات التي ينبغي على معالج FastCGI توقعها. غالبًا ما يضبط هذا الإعداد بالمتغير content_type$ فقط، والذي يضبط بدوره وفقًا للمعلومات المأخودة من الطلب الأصلي. CONTENT_LENGTH: يجب أن يضبط هذا الإعداد إن كان نوع الطلب هو POST. يشير هذا الإعداد إلى طول المحتوى، وغالبًا ما يضبط بالمتغير content_length$ والذي يأخذ قيمته من المعلومات المتوفّرة في طلب المستخدم الأصلي. SCRIPT_NAME: يستخدم هذا الإعداد ليُشير إلى اسم السركبت الأساسي الذي يجب تشغيله. وهو إعداد هامٌ للغاية يمكن ضبطه بعدّة طرق وفقًا لاحتياجاتك. عادةً ما يُضبط بالمتغير fastcgi_script_name$ والذي يجب أن يكون معرّف URI للطلب، أو معرف URI للطلب متبوعًا بـ fastcgi_index إن انتهى المعرّف بـ (/)، أو المجموعة اللاقطة الأولى إن استُخدم fastcgi_fix_path_info. SCRIPT_FILENAME: يحدّد هذا الإعداد الموقع الفعلي على القرص للسكربت الذي يجب تشغيله. وبسبب ارتباطه مع الإعداد SCRIPT_NAME، تقترح بعض أدلة الاستخدام Guides أن تستعيض عن استخدامه بالمتغيرين document_root$fastcgi_script_name$. يتوفر بديلٌ آخر يملك العديد من المحاسن وهو استخدام request_filename$. REQUEST_URI: ينبغي أن تحوي على معرّف URI للطلب كاملًا ومن من دون تعديل، بالإضافة إلى السكربت الذي يجب تشغيله، ومعلومات المسار الإضافية، وأي قيمٍ ممرّرة. تفضّل بعض التطبيقات أن تحلّل تلك المعلومات بنفسها، ويقدم هذا الإعداد المعلومات اللازمة لهم للقيام بذلك. PATH_INFO: إن ضُبط cgi.fix_pathinfo بالقيمة “1” في ملف إعدادات PHP، فسيحوي هذا الإعداد على أية معلومات مسار إضافية additional path information مذكورة بعد اسم السكربت. عادةً ما يُستخدم هذا الإعداد لتعريف الملف الممرّر file argument والذي سيحدّد تصرُّف السكربت. قد يترتّب على ضبط cgi.fix_pathinfo بالقيمة "1" آثارٌ أمنية إن لم تكن طلبات السكربت قد فُحصت بوسائل أخرى (سنناقش ذلك لاحقًا). قد يُضبط هذا الإعداد أحيانًا بالمتغير fastcgi_path_info$ والذي يحوي على المجموعة اللاقطة لثانية من التعليمة fastcgi_split_path_info. وفي حالاتٍ أخرى، سيكون هنالك حاجةٌ لاستخدام متغير مؤقت، إذ أنه يمكن لمعالجةٍ أخرى أن تمسح تلك القيمة أحيانًا. PATH_TRANSLATED: يربط هذا الإعداد بين معلومات المسار المحتواة ضمن PATH_INFO والمسار الفعلي على نظام الملفات filesysem path. عادةً ما يُضبط هذا الإعداد بـ document_root$fastcgi_path_info$، ولكن أحيانًا يجب استبدال المتغير الأخير بالمتغير المؤقت الذي أشرنا إليه سابقًا. التحقق من الطلبات قبل تمريرها إلى FastCGI إنّ أحد المواضيع بالغة الأهمية التي لم نغطها حتى الآن هو كيفية تمرير الطلبات الديناميكية للخادوم بشكلٍ آمن. إن تمرير كلّ الطلبات للخادوم الخلفي بغض النظر عن صحتها لا يسبب خفض فاعلية الخادوم فحسب، بل إنه خَطِرٌ أيضًا. إذ أنه من الممكن للمهاجمين إنشاء طلباتٍ خبيثة في محاولةٍ منهم لتشغيل نص برمجي ما. في الواقع، حتى نعالج هذا الخطأ علينا أن نضمن إرسال الطلبات الصالحة فقط لمعالج FastCGI، يمكننا القيام بذلك بعدة طرق وذلك تبعًا لاحتياجات إعدادنا الخاص وفيما إن كان معالج FastCGI يعمل على نفس النظام المشغِّل لـ Nginx أم لا. إحدى القواعد الأساسية التي يجب أن تحدد لنا كيفية ضبط الإعدادات، هي أنه علينا ألا نسمح بأي معالجة أو تفسير لملفات المستخدم. إذ أنه من السهل نسبيًا على المستخدمين المخادعين malicious users أن يضمّنوا نصًا برمجيًا صالحًا valid code في ملفاتٍ تبدو في الظاهر أنها ملفاتٍ غيرُ مؤذيةٍ كالصور. حالما يُرفع ملفٌ كهذا إلى الخادوم علينا أن نضمن ألا يجد طريقًا للوصول إلى معالج FastCGI. إنّ المشكلة الأساسية التي نحاول حلها هنا هي في الواقع محدّدةٌ في مواصفات CGI specification. تتيح لك تلك المواصفات تحديد ملف السكربت الذي ترغب بتشغيله متبوعًا بمعلومات المسار الإضافية التي يمكن للسكربت أن يستخدمها. إن نموذج التنفيذ هذا يسمح للمستخدمين بطلب معرف URI قد يبدو كسكربت صالح legitimate، إلا أن الجزء الذي سيتم تنفيذه سيكون مذكورًا قبله في المسار. فالنأخذ مثلًا طلبًا لـ: test.jpg/index.php/ إن كانت إعداداتك تمرّر ببساطة كل الطلبات التي تنتهي بـ .php إلى المعالج دون التحقق من مدى صحتها فسيتحقق المعالج، إن كان يحقّق المواصفات، من وجود ذلك الموقع وسينفذّه إن أمكن. أما إذا لم يجد الملف فسيتّبع المواصفات وسيحاول تنفيذ الملف test.jpg/ وسيعتبر أن index.php/ تمثّل معلومات المسار الإضافية الخاصة بالسكربت. كما ترى يمكن لذلك أن يسمح ببعض النتائج غير المرغوب بها إطلاقًا عندما يجتمع مع فكرة رفع المستخدم للملفات. هنالك مجموعة من الطرق المختلفة لحل تلك المشكلة. أسهل تلك الطرق هو ببساطة تعطيل خاصية معالجة معلومات المسار من قِبَل المعالج، وذلك إن كان تطبيقك لا يعتمد على تلك المعلومات الإضافية. يمكن تعطيل تلك الخاصية لدى PHP-FPM من خلال الملف php.ini، فمثلًا إن كنت تستخدم نظام أوبونتو Ubuntu فيمكن تحرير الملف التالي: sudo nano /etc/php5/fpm/php.iniببساطة، ابحث عن الخيار cgi.fix_pathinfo وألغِ تعليقه ثم اضبطه بالقيمة “0” لتعطّل هذه “الميزة” كما يلي: cgi.fix_pathinfo=0أعد تشغيل عملية PHP-FPM حتى تأخذ التعديلات حيّز التنفيذ: sudo service php5-fpm restartسيدفع ذلك PHP لتنفيذ الجزء الأخير من المسار فقط، وبالتالي ففي المثال السابق إن لم يكن الملف test.jpg/index.php/ موجودًا فسيصدر PHP خطأ عوضًا عن محاولة تنفيذ الملف test.jpg/ إذا كان معالج FastCGI يعمل على نفس الخادوم الذي يُشغل Nginx فلدينا خيارٌ آخر وهو ببساطةٍ التحقق من وجود الملفات على القرص قبل تمريرها إلى المعالج. فإذا لم يكن الملف التالي موجودًا test.jpg/index.php/ فسيصدر خطأ. أما إن كان موجودًا فسيُرسل إلى الخادوم الخلفي لتتم معالجته. سينتج عن ذلك عمليًا سلوكٌ يشبه إلى حد بعيد ما رأيناه سابقًا. location ~ \.php$ { try_files $uri =404; . . . }إن كان تطبيقك يعتمد في سلوكه على معلومات المسار حتى يقوم بعملية التفسير بشكل صحيح فما زال بإمكانك السماح بتطبيق ذلك السلوك بأمان عبر القيام بالاختبارات قبل اتخاذ قرارٍ بإرسال الطلب إلى الخادوم الخلفي. فمثلًا، بإمكاننا مطابقة المجلدات التي نخرن فيها الملفات المرفوعة غير الموثوقة تحديدًا وضمان ألا تمرّر إلى المعالج. مثلًا، إن كان مجلد الملفات المرفوعة على المسار: /uploads/ فعلينا إنشاء مقطع موقع يتم مطابقته قبل أن يتم تقييم أي عبارة منتظمة: location ^~ /uploads { }بإمكاننا إضافة أي نوع من معالجة ملفات PHP داخل المقطع البرمجي: location ^~ /uploads { location ~* \.php$ { return 403; } }سيعمل الموقع الأم parent location على مطابقة أي طلب يبدأ بـ uploads/ وأيُّ طلب يتعامل مع ملفات PHP سيُرد عليه بالخطأ 403 عوضًا عن إرساله إلى الخادوم الخلفي. يمكنك أيضًا استخدام التعليمة fastcgi_splite_path_info للتعريف يدويًا عن الجزء من الطلب، الذي يجب تفسيره كسكربت والجزء الدي يجب تعريفه على أنه معلومات المسار الإضافية باستخدام التعابير النمطية. يسمح لك ذلك بأن تستمر في الاعتماد على وظيفة معلومات المسار، على أن تعرّف بدقة ما تعتبره بريمجًا وما تعتبره مسارًا. فمثلًا، بإمكاننا إعداد مقطع لموقع يقوم باعتبار أن أول جزء مكون للمسار ينتهي ب .php هو السكربت الذي ينبغي تشغيله. ويعتبر الباقي معلومات المسار الإضافية. وذلك يعني أنه من أجل الطلب: test.jpg/index.php/ فسيتم إرسال كامل المسار إلى المعالج باعتباره اسم السكربت ولا يحوي معلومات مسار إضافية. يمكن أن يكون الموقع كالآتي: location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(.*)$; set $orig_path $fastcgi_path_info; try_files $fastcgi_script_name =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param PATH_INFO $orig_path; fastcgi_param PATH_TRANSLATED $document_root$orig_path; }ينبغي أن يعمل المقطع السابق عندما تكون قيمة cgi.fix_pathinfo في إعداد PHP مضبوطةً بالقيمة "1" حتى تسمح بمعلومات المسار الإضافية. وهنا، إن مقطع الموقع السابق لا يطابق الطلبات التي تنتهي بـ .php وحسب، بل تلك التي تنتهي بـ .php قبل إشارة "/" مباشرةً والتي تدل على مكون إضافي يتبع مسار المجلد directory. تعرّف التعليمة fastcgi_split_path_info داخل المقطع مجموعتين لاقطتين captured group باستخدام التعابير النمطية. تطابق المجموعة الأولى الجزء الممتد من بداية عنوان URI وحتى أول ورود لـ .php ويضعه في المتغير fastcgi_script_name$. ومن ثم يضع أي معلومة مذكورة في الجزء الباقي، والممتد بدءًا من النقطة التي انتهى عندها الجزء الأول وحتى نهاية العنوان، في المجموعة اللاقطة الثانية والتي تخزّن في متغير يدعى fastcgi_path_info$. نستخدم التعليمة set لنخزن القيمة المحفوظة في fastcgi_path_info$، حتى هذه النقطة، في متغير يدعى orig_path$. وذلك لأن قيمة المتغير fastcgi_path_info$ ستُمحى في لحظة عبر التعليمة try_files. بإمكاننا التحقق من اسم السكربت الذي التقطناه سابقًا باستخدام التعليمة try_files. وهي عبارة عن عملية تطبّق على ملف file operation تتأكد من أنّ السكربت الذي نحاول تشغيله مخزن على القرص. ولكن لذلك تأثيرًا جانبيًا يتمثل في مسح قيمة المتحول fastcgi_path_info$. بعد القيام بالتمرير التقليدي عبر FastCGI فإننا نضبط SCRIPT_FILENAME كما العادة. نضبط أيضًا الإعداد PATH_INFO بالقيمة التي المخزّنة في المتغير orig_path$. فبالرغم من أن قيمة fastcgi_path_info$ قد مُسحت، إلا أن قيمته الأصلية محفوظة في ذلك المتغير. كما أننا نضبط الوسيط PATH_TRANSLATED ليربط map بين معلومات المسار الإضافية والموقع الذي تُحفظ فيه على القرص، نقوم بذلك عبر دمج قيمتي المتغيرين document_root$ و orig_path$. يسمح لنا ذلك ببناء طلباتٍ مثل: index.php/users/view/ بحيث يتمكن الملف: index.php/ من معالجة المعلومات المتعلقة بالمجلد: users/view/ وبنفس الوقت نتجنب المواقف التي سيُشغّل بها الطلب: test.jpg/index.php/ سيُضبط البريمج دائمًا بأقصر مكوّن ينتهي بـ .php، وبالتالي سنتجنب تلك المشكلة. يمكننا أيضًا تحقيق ذلك باستخدام تعليمة alias إن احتجنا إلى تغيير موقع ملفات السكربتات. علينا فقط أن نأخذ ذلك بالحسبان في كل من ترويسة الموقع وتعريف fastcgi_split_path_info. location ~ /test/.+[^/]\.php(/|$) { alias /var/www/html; fastcgi_split_path_info ^/test(.+?\.php)(.*)$; set $orig_path $fastcgi_path_info; try_files $fastcgi_script_name =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param PATH_INFO $orig_path; fastcgi_param PATH_TRANSLATED $document_root$orig_path; }سوف يسمح لك ذلك لتشغيل تطبيقاتك التي تستخدم الإعداد PATH_INFO بأمان. تذكّر أنه عليك تعديل الخيار cgi.fix_pathinfo في ملف php.ini وضبطه بالقيمة "1" حتى يعمل بشكل صحيح. قد يترتب عليك أيضًا أن تعطّل security.limit_extensions في الملف php-fpm.conf. الخلاصةنأمل أنك تملك الآن فهمًا أفضل لإمكانية قيام FastCGI بالوساطة عنNginx. تسمح هذه الإمكانية لـ Nginx باستخدام قوته في معالجة الاتصالات بسرعة وتحضير المحتوى الثابت static content، بينما تُحمّل مسؤولية المحتوى الديناميكي dynamic content لبرمجيات مناسبة لذلك. يسمح FastCGI لـ Nginx بالعمل مع عدد كبير من التطبيقات، عبر إعدادات آمنة وذات أداء. ترجمة – وبتصرّف– للمقال Understanding and Implementing FastCGI Proxying in Nginx لمؤلفه Justin Ellingwood.