لنجعل مواقعنا أسرع – الويب سيرفر

في الجزء السابق من هذه السلسلة تحدثت عن بعض النصائح و التلميحات المهمة التي يمكن تطبيقها على واجهة المستخدم لجعل مواقع الويب أسرع و أصغر حجماً . في هذا الجزء سأتحدث عن التعديلات التي يمكنك إجراءها على خادم الويب ( Web Server ) ، و بما أن الغالبية العظمى من مواقع الويب العربية تعمل على Apache فسأخصه بالشرح ، معظم ما سيذكر سيكون قابل للتطبيق بشكل أو بأخر على خوادم الويب الأخرى مثل IIS أو IBM IHS .

ملاحظة هامة : هذه المقالة تفترض أن لديك وصول إلى ملف إعدادات الأباتشي httpd.conf و لديك معرفة بكيفية عمله و سبق أن تعاملت معه.

الهاردوير .. ليس الحل دائماً !

عندما يواجه بعض أصحاب المواقع الضخمة مشاكل في الأداء و السرعة ، يتبادر إلى ذهنه أن الوقت قد حان لإقتناء سيرفر أفضل بعدد معالجات أكبر و ذاكرة أعلى و غيرها من المواصفات الخاصة بالعتاد Hardware . خاصة إذا شاهد بعينه أن مستوى إستهلاك الذاكرة و المعالج يقترب من الـ 100 % . قد يكون فعلاً خادم الموقع بحاجة إلى ترقية عتاد ، ولكن هذا ليس دائماً الحل ، بل دعني أقول ان الغالبية العظمى من الحالات التي باشرتها بنفسي كانت المشكلة تتعلق بأمور أخرى لا علاقة لها بالعتاد نهائياً . بعض الحالات كان مجرد تغيير في أحد إعدادات الأباتشي كفيل بتحسين الأداء بمقدار 4 أضعاف الوضع السابق . لذلك قبل أن تقرر شراء سيرفر جديد أو ترقية سيرفرك الحالي ، حاول أن تستغرق وقت طويل في تجربة سلسلة من التغييرات في الإعدادات الخاصة بنظام الويب سيرفر الخاص بموقعك.

إعدادت الأباتشي

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

الإعدادات Configurations في أي نظام هي سلسلة من حلقات مترابطة تؤثر على بعضها ، فرفع قيمة معينة قد لا يجدي نفعاً الا اذا خفضت قيمة أخرى ، و العكس صحيح ، اذاً عليك أن تعرف مبدئياً أن التأثير الإيجابي لتغيير الإعدادات يأتي من توليفه معينة من الإعدادات و ليس بتعديل كل خاصية على حده. لهذا السبب أيضاً يتطلب الأمر منك التجربة و العمل بطريقة المحاولة و الخطأ Trial & Error و رصد كافة التغيرات التي تطرأ للوصول إلى التوليفة المناسبة لموقعك .

أولاً : إختيار الـ MPM المناسب

سيرفرات الأباتشي يمكن بنائها بحيث تتضمن أحد هذه الأنواع من وحدات المعالجة المتعددة Multi-Processing Modules (أو MPM إختصاراً) و التي تكون وظيفتها بشكل رئيسي تحديد طريقة اتصال السيرفر بالشبكة و معالجة الطلبات القادمة HTTP Requests و الرد عليها HTTP Responses .  وحدات المعالجة MPM في الأباتشي هي :

1- وحدة المعالجة Prefork :

– وحدة متعددة العمليات Processes ، كل عملية تحتوي على Thread واحدة ، و العملية Process هي التي تتولى عملية الرد على الطلبات HTTP Requests / Responses

– كل عملية Process يمكن أن تعمل بحساب مستخدم موجود على النظام ، مما يجعل وحدة المعالجة Prefork أفضل من الناحية الأمنية

– لكون كل عملية Process تحتوي على Thread واحدة ، فإن وحدة المعالجة Prefork تستهلك ذاكرة أعلى و قدرتها الأدائية أقل.

2- وحدة المعالجة Worker :

– وحدة متعددة العمليات Processes ، كل عملية يمكن أن تحتوي على أكثر من Thread ، و الـ Thread الواحد هو الذي يتولى عملية الرد على الـ HTTP Requests / Responses

– أقل إستهلاكاً للذاكرة و أدائها أفضل من سابقتها ، خيار مثالي اذا كان سرعة الأداء أولوية قصوى لك

– عمليات المعالجة غير معزولة بشكل كامل ، كل عملية Process يمكنها أن تقوم بعدد غير محدود من عمليات المعالجة لكون الـ Thread هو من يستقبل الطلب و ليس العملية Process

3- وحدة المعالجة Winnt

– اذا كنت تشغل الأباتشي على ويندوز ، فهذا هو الخيار الوحيد لك 🙂

– لأن ويندوز نظام يعالج الـ Threads بشكل أفضل من العمليات Processes ، فإن هذه الوحدة تعمل ب Process واحدة فقط و عدد من الـ Threads .

تذكر أنه يمكنك إختيار واحدة فقط من هذه الوحدات لكي يعمل الأباتشي بها ، و يتم اختيارها عند عملية الـ Compilation . إختيار وحدة المعالجة MPM المناسبة يعتمد كلياً على أولوياتك و على عدد من العوامل ، مثل دعم نظام التشغيل للـ Threads و عدد المعالجات و حجم الذاكرة و نوعيتها في السيرفر و كذلك على طبيعة الترافيك القادمة للموقع و كمية الـ HTTP Requests و مفاضلتك بين قابلية التوسع Scaleability و الثبات Stability .

ثانياً : إعدادات وقت التشغيل Run-Time

جميع الإعدادات التي سنتحدث عنها ستجدها في ملف httpd.conf وهو الملف المسؤول عن إعدادات الأباتشي . لاحظ هنا أنني سأشرح الإعدادات الخاصة بوحدة المعالجة Worker حيث أنها الوحدة التي ينصح بإستخدامها غالباً في السيرفرات الحديثة التي تدعم الـ Threads ، بعض الإعدادات التي سأشرحها مشتركة بين النوعين . اذا احتجت ان تستخدم Prefork فيمكنني مساعدتك لإيجاد القيم المثلى ، لا تتردد بسؤالي 🙂

1- HostnameLookups

هذا الموجه Directive مستنزف حقيقي للترافك و الوقت من سيرفرك ، حيث يقوم بعملية فحص للـ DNS ( أو ما يعرف بـ DNS Lookup ) و ذلك لكل طلب يصل للسيرفر ! حيث يقوم بفحص أي بي الزائر و التحقق من مصدره و نطاقه لتسجيله في سجلات الدخول access_log . عملية لا أجد حاجة لها في معظم السيرفرات ، لذا تأكد أن قيمة هذا الموجه هي Off .

2- AllowOverride

هذا الموجه Directive يخبر الأباتشي ما اذا كانت ملفات الـ .htaccess على السيرفر يمكن إعادة تجاوزها في أي مسار على السيرفر ، فمثلاً اذا كانت قيمة AllowOverride هي All ، و عند قدوم طلب لتصفح العنوان التالي /index.php فإن الأباتشي سيقوم بالتجول في المجلدات الفرعية /sub1 و /sub1/sub2 و /sub1/sub2/sub3  ! تخيل ان هذه العملية تتم عند كل طلب ! لا داعي لذلك ، اذا احتجت استخدام ملفات .htaccess فأجعلها في كل مجلد في موقعك و لا تعتمد على أن السيرفر سيستطيع رؤيتها من أي مكان .

3- MaxClients

قيمة هذا الموجه حساسة و مهمة للوصول إلى أفضل أداء ممكن ، سواء كنت تستخدم وحدة المعالجة Prefork أو Worker . هنا يمكنك تحديد العدد الأقصى من العمليات Processes أو إجمالي عدد الـ Threads التي ستعمل في السيرفر لخدمة الزوار و إستقبال الطلبات HTTP Requests . لو كنت تستخدم وحدة المعالجة Prefork فإن ضبط قيمة MaxClients سيكون سهل ، و لكن بما أننا قررنا الحديث عن وحدة المعالجة Worker فإن عملية الضبط ستكون أصعب بكثير. MaxClients في وحدة المعالجة Worker تعني عدد الطلبات HTTP Requests التي يمكن للسيرفر إستقبالها في نفس اللحظة . المشكلة هنا أنك تريد وضع رقم يسمح لسيرفرك بتقديم أفضل أداء و لا يجعل الزائر ينتظر حتى يحصل على إتصال و بنفس الوقت لا تريد الرقم أن يصبح كبيراً جداً ليستهلك الذاكرة و يرهق موارد النظام . حسناً أظن أنك خمنت الحل ، لا يوجد معادلة أو قيمة سحرية ، ذلك يعتمد كلياً على طبيعة الطلبات التي ترد لموقعك وحجمها و تزامنها ، لذلك فأنت تحتاج إلى تجربة عدة قيم حتى تصل للقيمة المثلى. أبقي عينيك على إستهلاك الذاكرة مع كل تغيير . كما حاول تغيير ThreadsPerChild و التي سنتحدث عنه بعد قليل.

4- ThreadsPerChild

في وحدة المعالجة Worker من يقوم بعملية استقبال الطلب و معالجته فعلياً هو الـ Thread و ليس الـ Process ، لذلك فإن تحديد عدد الـ Threads لكل عملية Process قائمة هو أمر مهم. هذا الموجه Directive سيعتمد عليه الأباتشي في تحديد عدد العمليات الـ Processes التي سينشأها الأباتشي . حين يضطر الأباتشي لإنشاء Process جديدة ، فإنه يقوم بإنشاء Threads بالعدد الذي تحدده هنا ، سواء كان هناك طلبات إتصال بهذا العدد أو لا ، فإن جميع الـ Threads سيتم إنشائها بمجرد إنشاء الـ Process الجديدة ، لذلك كن حذر من رفع العدد بصورة مبالغ فيها. الخطورة هنا تكمن في أن حدوث مشكلة جذرية في أحد الـ Threads قد يؤدي إلى توقف الـ Process كاملها عن العمل و قتلها من قبل النظام . أحد أكثر الأسباب التي تؤدي إلى ذلك هو رفع قيمة الـ ThreadsPerChild إلى قيمة أعلى مما ينبغي.

5- StartServers

هذا الموجه Directive الذي يسمح لك بتحديد عدد الـ Processes الذي سيبدأ فيه الأباتشي عند أول تشغيل له ، كل Process بالتأكيد ستقوم بإنشاء عدد من الـ Threads المحدد في الموجه ThreadsPerChild .

6- MinSpareThreads

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

7- MaxSpareThreads

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

8 – MaxRequestsPerChild

هذا هو عدد الطلبات HTTP Requests الذي ستقوم الـ Process بخدمتها بكل الـ Threads المتواجدة فيها ، قبل أن تعلن إعتزالها و تخرج من الذاكرة 🙂 ! لو فرضنا أن العدد هو 1000 ، هذا يعني ان كل Process ستقوم بخدمة ألف طلب ثم تغلق جميع المنافذ ويقوم الأباتشي بإنهاء خدماتها !. القيمة الإفتراضية لهذه الخاصية هي 0 (صفر) ، و التي تعني انه لا حدود لعدد الطلبات التي سيتولى تلبيتها كل Process و لن يتم إنهاء خدمات أي منها الا اذا كان الغرض من الإنهاء الوصول إلى MaxSpareThreads في حالة قلة الطلب على السيرفر.

و لكن ، لماذا يكون من الضروري أحياناً ان يقوم الأباتشي بإنهاء خدمات أي Process بعد تأديتها عدد من الطلبات ؟ حسناً ، هذا يفيد لتفادي مشاكل تسرب الذاكرة Memory Leak التي تنتج بسبب بقاء العملية لوقت طويل جداً في الذاكرة مما يجعل مخلفات هذه العملية تتراكم بسبب خلل في عملية تجميع المخلفات Garbage Collection . اضف إلى ذلك حاجة السيرفر بشكل عام إلى إستخدام أجزاء من الذاكرة لعمليات أخرى مختلفة ليس لها علاقة بالأباتشي.

9- mod_deflate

هذه الوحدة Module يمكنك تضمينها من خلال ملف httpd.conf و ستعمل على ضغط الردود HTTP Responses على الطلبات مما يوفر الترافك بنسبة تصل إلى 75 % في بعض الأحيان. يمكنك تحديد أنواع الملفات التي ستتعرض للضغط . لاحظ ان عملية الضغط بحد ذاتها تستغرق وقت ، لذا يجب عليك الموازنه بين حاجتك لضغط الملفات لتسريع نقلها و بين الوقت الذي ستسغرقه عملية الضغط هذه.

10 – mod_expires

هذه الوحدة مسؤولة عن عملية التحكم بالتخزين المؤقت Caching على جهاز المستخدم و ذلك بتحديد تاريخ إنتهاء صلاحية المحتوى حسب عدة عوامل مثل تاريخ التعديل أو تاريخ الوصول للملف. مثلاً :

ExpiresByType text/html “access plus 1 month 15 days 2 hours”

في هذا السطر حددت تاريخ صلاحية ملفات الـ HTML لمدة شهر واحد و 15 يوم و ساعتين و ذلك من تاريخ الوصول اليها ، بمعنى عند تصفح الزائر لصفحتك لأول مرة فأنها ستخزن في ملفاته المؤقته و سيستمر في تصفحها من الملفات المؤقته لمدة شهر و 15 يوم و ساعتين عند طلبها مجدداً ، سيلغى هذا الشرط اذا حذف الزائر ملفاته المؤقته أو طلب بشكل صريح أحدث نسخة من الصفحة Ctrl + F5 .

هناك تطبيقات و خصائص كثيرة لهذا الـ Module ، أنصح بالقراءة عنه بشكل متعمق.

11- KeepAlive

لإبقاء الإتصال مفتوحاً مع الزائر ، هذه الخاصية تسمح بسرعة تنفيذ الطلبات بدلاً من إغلاق الإتصال و فتحه عند كل طلب يأتي من نفس الزائر ، يمكنك السماح بها On أو إغلاقها Off . هناك خاصيتان مرتبطتان بهذا الموجه:

KeepAliveTimeout : عدد الثواني الذي سيظل الإتصال فيها مفتوحاً مع الزائر قبل أن يتم إغلاقه ، رفع هذه القيمة قد يؤدي إلى حجز عدد كبير من الإتصالات لمدة طويلة مع عدد محدد من الزوار مما يؤخر خدمة زوار آخرين ! في وحدة المعالجة Worker قد تكون 10 أو 15 ثانية قيمة عادلة. ولكن ذلك يعتمد كلياً على عدد العناصر في صفحات موقعك و حجمها و سرعة التحميل و تدفق الزوار في نفس اللحظة !

MaxKeepAliveRequests : عدد الطلبات التي سيرد عليها الـ Thread أثناء عملية الإتصال الواحدة TCP Connection قبل أن يقوم بإغلاق الإتصال مجبراً متصفح الزائر على طلب إتصال جديد. أيضاً تعتمد هذه الخاصية على عدد العناصر في صفحات موقعك و طبيعة تصفح زوار الموقع لموقعك و سرعة تنقلهم بين الصفحات.

12 –  ExtendedStatus

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

13 – Timeout

في حال فشل أحد الطلبات في الوصول بشكل كامل و صحيح للسيرفر ، فكم ثانية يجب على الـ Thread أن تنتظر قبل أن تعلن إنتهاء الوقت و فشل الطلب و الإنتقال لخدمة طلب آخر. قم بتقليل هذه المدة إلى حد معقول. تقليلها بشكل مبالغ فيه قد يؤدي إلى إغلاق الإتصالات بشكل متزايد في وجه الطلبات التي تستغرق ثواني إضافية كي يكتمل وصولها !!

أخيراً …

أعلم أن هذا الجزء قد يكون صعب الفهم لأني حاولت تغطية معظم الخصائص التي تساعد في تحسين أداء الأباتشي و بنفس الوقت حاولت الإيجاز وعدم التعمق ببعض التفاصيل التي لا تنطبق على معظم الحالات ، كما أني واجهت مشكلة في تعريب بعض المصطلحات و بعضها عربتها إجتهاداً و لا أدري إن كان لها تعريب متعارف عليه أفضل من الذي اخترته. لذا أرجو من أي شخص يواجه صعوبة في فهم بعض الأمور أن يطرح سؤاله و سأكون سعيداً بالإجابة عليه. خلاصة القول أن ضبط إعدادات الويب سيرفر بشكل عام هو بحر لا قرار له ، لأن الإعدادات هي سلسلة مترابطة بعضها يؤثر على الآخر ، و رفع قيمة قد يتطلب خفض أو رفع قيمة أخرى و هكذا …

 

الجزء القادم سيكون بإذن الله عن أفضل الممارسات لتطوير تطبيقات سريعة و فعالة بإستخدام PHP

  • UA3

    حقاً، تطوير الهاردويير ليس الحل دائماً، لدي سيرفر قديم املكه منذ سنتان، كان مخصص لموقع واحد عدد زواره لا يتجاوز 300 ألف شهرياً، ولكن خلال الستة اشهر الاخيرة زاد الزوار في الموقع بشكل مضاعف حتى وصل الى 1,500,000 زائر شهرياً، بدأت ألاحظ بطيء شديد في اوقات الذروة واستهلاك كبير لموارد السيرفر، بدأت التفكير جدياً بالانتقال لسيرفر اقوى، ولكن قبل ذلك قمت بتجربة التعديل على بعض الاعدادات في الاباتشي (معظمها ذكرت في المقال) وكانت النتائج مذهلة حقاً واصبح تصفح الموقع خفيف جداً وسريع وسلس، وانخفض استهلاك الباندويث او الترافيك الى النصف.

    مقال رائع حقاً ومفيد لجميع اصحاب السيرفرات.
    انصح وبشدة تطبيق ما جاء فيه وحفظه في المفضله لأوقات الحاجة.

    تحياتي

    • شكراً أستاذي الكريم على مشاركتك لنا لقصتك التي تحكي مثالاً حياً لما أتحدث عنه في المقالة. الشكر موصول لك و تمنياتي لك بالتوفيق

  • Hany

    ماشاء الله تبارك الله
    جهد كبير ورائع بكل المقاييس
    لست مختصا ولا املك او افقه في كثير من جوانب هذا المقال ولكن احببت أن أشكرك اخي ناصر، فمقالك هذا يعتبر مرجعا للمهتمين

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

    • كلماتك الجميلة أستاذي وسام أعلقه على صدري .. يزيدني شرفاً شهادتك في كلماتي المتواضعة. من واجبي الشرعي و الأخلاقي أن لا أكتم العلم و أنشره ليستفيد منه الجميع … أتمنى أن يقدرني الله على نشر المزيد من المواضيع و المقالات.

  • متصفح

    مقالة رائعة ومفيدة وفريدة بمعلوماتها المفصلة والجديدة.. أقرأ منذ سنوات في تطوير الوب وهذه أول معلومات مفصلة تتناول جانب سيرفرات الوب أجدها. بارك الله فيك وجزاك خيرا أخ ناصر.

تعليقات عبر الفيسبوك