היסטוריית גירסאות | ||
---|---|---|
גירסא 1.0 | 03-04-2007 | כתריאל טראום |
גירסא ראשונה | ||
גירסה 0.1 | 31-03-2007 | כתריאל טראום |
טיוטאת שלד |
מדריך זה ידבר על הרכיבים הנפוצים בהרבה מאתרי האינטרנט היום: Linux, Apache, MySQL & PHP וכיצד ניתן למטב אותם כדי לענות לעומסים גדולים יותר.
רובנו, כאשר אנו מקימים אתר LAMP, עושים זאת בצורה של “שגר ושכח”: מתקינים, מקנפגים בצורה בסיסית כדי שהרכיבים “ידברו” ומתחילים לעבוד על האפליקציה\תוכן שלנו. מדריך זה בא להראות שלפני התוכן, ואחרי ההתקנה, שווה לעבוד עוד קצת, כדי להוציא את המקסימום מהאפליקציות והחומרה שיש לנו. במדריך זה אעבור רכיב רכיב, ואראה דרכים לשיפור הביצועים שלו, כמובן שה”שיפצורים” יהיו מוכוונים לשרת שהולך להיות שרת Web.
כל הזכויות שמורות © 2007, כתריאל טראום, הרשות ניתנת להעתיק, לשנות ולהפיץ מדריך זה תחת התנאים של רשיון ה-GFDL
Linux הוא סימן מסחרי רשום של Linus Torvalds.
הכותב אינו נושא באחריות עבור שימוש ברעיונות, דוגמאות ומידע שבמדריך. השימוש הוא באחריות הקורא בלבד. המדריך עשוי להחיל טעויות ופרטים לא נכונים, שהשימוש בהם עשוי להיות מזיק למחשבך. למרות הסבירות הנמוכה, הכותב אינו לוקח כל אחריות
תגובות, תלונות, הערות והארות לכתובת בראשית הדף
בעולם שכולו טוב, משיקים אתר חדש, ובתוך יום כבר היה לנו מליוני כניסות יחודיות. בעולם פחות מושלם, צריך להתחיל בקטן, ולקוות שנגדל יום אחד. תנאי חשוב לגידול קל של המערכת שלנו הוא תכנון טוב מראש.
כבר בשלב התיכנון כדאי לתכנן את רכיבי החומרה והתוכנה שיהיו קלים להרחבה בעתיד. מומלץ תמיד להשתמש ברכיבים טובים יותר (ניתן לקרוא גם “יקרים יותר”) שיוכלו לשאת ביותר עומס ממה שהמערכת מתוכננת מראש.
הפרמטרים החשובים ביותר כאשר מקימים אתר LAMP הם זכרון, דיסק ומעבד (איזה הפתעה). זכרון עבוד Caching, דיסק מהיר בשביל קריאה התוכן כאשר אין אוביקט בזיכרון ומעבד בעיקר עם יש לכם אפליקציה דינאמית.
החל מקרנל 2.6, נתן לכוונן כיצד מערכת ההפעלה תקרא ותכתוב מהדיסק. ישנן שיטות “קיבוץ” פעולות I/O שונות אשר נותנות ביצועים טובים במצבים שונים. השיטות הן:
כדי לקבוע את סוג המתזמן (Scheduler) יש להשתמש ב-sysfs ע”י כתיבת שם המתזמן; as, cfq, deadline או noop לתוך הקובץ:
/sys/block/<devicename>/queue/scheduler
עבור שרת Apache עמוס, ה-Anticipatory Scheduler אמור לספק שיפור ביצועים באתר אשר יש בו קריאה רבה מהדיסק.
גם בנושא זה, האפשרויות מגוונות, לכל מערכת קבצים חוזק אחר.
בנושא הזה אין “כלל אצבע”, עליכם להכיר את האתר והתוכן שאתם מתכוונים לשרת, ולהחליט על בסיס המידע הזה איזו מערכת קבצים תתאים לכם. עצתי היא בכל מערכת קבצים שלא תבחרו, השוו תוצאות של כלי בדיקת עומסים תחת מצבים קרובים ביותר לתוכן האתר שלכם. מומלץ להשתמש בתוכנות bonnie++ ו- iozone תוך דימוי קרוב ביותר לאתרכם מול כמה מערכות קבצים שונות.
צד אחר של מערכת ווב פעילה, הוא ה-Networking. גם כאן נוכל לבצע מספר שינויים בכדי לשפר את ה-Throughput של השרת שלנו. את הערכים הבאים אפשר להוסיף לקובץ sysctl.conf או דרך סקריפט אחר שמבצע את הכיוונים האלו:
fs.file-max=5049800 net.ipv4.tcp_keepalive_time = 300 net.ipv4.tcp_max_orphans=1000 sys.net.core.rmem_default=262144 sys.net.core.rmem_max=262144
MPM או Multi-Processing Modules הם מודולים שונים שמנהלים את אפאצ'י והתהליכים שלו (Processes) בדרכים שונות. 2 ה-MPM-ים העיקריים הם prefork ו-worker. ה-MPM ברירת המחדל ברוב המערכות היום הוא prefork, וכך גם בנויים לרוב המודולים הנלווים ל- Apache בהפצות לינוקס.
StartServers 8 MinSpareServers 2 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000
StartServers 2 MaxClients 150 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0
השימוש ב-Prefork יתרום לרוב במערכות בעלות מעבד אחד או-2, והוא יותר עמיד בפני נפילות של תהליכים ומודולים בעיתיים. Worker MPM מתאים יותר למערכות מרובות מעבדים אשר יוכלו לנצל טוב יותר את האופי ה-Multithreaded שלו ואת ניצול הזכרון הנמוך יחסית. מצד שני, מכיוון שהוא Threaded ברגע שתהליך אחד עף, כל ה-threads שהוא מנהל ימותו גם כן.
MaxClients = <Apache RAM> / Process Size
לא רצוי לעלות מעבר לכמות ה-RAM שיש לשרת, כי אז יתחיל תהליך של swapping וביצועי המערכת יפגעו קשות.
כרגיל, אין כאן כלל אצבע, שניהם צריכים להיבחן לצרכים שלכם.
כדי לאפשר אופציה זאת יש לאפשר את האופציה Sendfile:
EnableSendfile On
<Directory /srv/www/html> AllowOverride all </Directory>
יחפש את הקובץ .htaccess בספריות:
במידה והקובץ .htaccess לא נחוץ, קריאה נוספת לדיסק בעבור כל ספריה היא מעמסה מיותר על מערכת ה-I\O.
Caching של מידע נעשה ברמות שונות בזמן מעבר התוכן מהשרת ללקוח: ב-RAM של השרת, Proxy שיושב בתווך, הדפדפן של המשתמש ועוד. שכבת Cache נוספת שעשויה לשפר את הביצועים של שרת Apache היא לבצע caching של תוכן שמשרת שרת ה-Apache על דיסקים מהירים או בזכרון. החל מ-Apache 2.0 ועם שיפורים ניכרים ב Apache 2.2 נוסף מודול שנקרא mod_cache אשר מסוגל לבצע caching של תוכן בזכרון המכונה או על דיסקים מהירים יותר ולשרת כך תוכן נפוץ בצורה מהירה יותר. מידע נוסף ניתן למצוא בקישור http://httpd.apache.org/docs/2.0/mod/mod_cache.html
ב- Apache 1.3 קראו למודול mod_gzip והוא הגיע כמודול חיצוני, החל מ- Apache 2.0 הוא מגיע כחלק מהחבילה ונקרא mod_deflate. מודול זה מאפשר לכווץ את המידע לפני שהוא נשלח ללקוח הקצה, כמובן במידה והלקוח תומך בתוכן מכווץ. אופציה זו מאפשרת זמני חיבור קצרים יותר מצד הלקוחות, וכך בעצם מאפשרת ל-Apache לשרת יותר לקוחות. בונוס נוסף הוא כמובן חיסכון ברוחב פס.
כדי לאפשר את mod_deflate, נשים את הקונפיגורציה הבאה:
AddOutputFilterByType DEFLATE text/html text/plain text/xml BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html Header append Vary User-Agent env=!dont-vary
אופציה זו אומרת ל-Apache לכווץ תוכן טקסטואלי בלבד (אין טעם לכווץ תמונות שבד”כ באות גם ככה בפורמט מכווץ כל שהוא), ומוסיפה כמה תנאים כדי לפתור בעיות עם דפדפנים ישנים יותר. ניתן לשים את האופציה בקונפיגורציה הכללית או בתוך הגדרה של Virtual Server.
נושא אחד שיש לשים לב אליו הוא שכיווץ לא בא ללא מחיר. המחיר הוא שימוש גדול יותר ב- CPU לצורך כיווץ המידע. לכן גם פה, אין כלל אצבע, ויש לעקוב אחרי ההשפעה של הפעלת mod_deflate על ביצועי השרת.
שרת ה-SQL בכל אתר תוכן דינאמי יכול להיות צוואר בקבוק במידה ולא נטפל בו כמו שצריך. העיצה הכי טובה שאני יכול לתת היא, במידה ואפשר, לשים את שרת ה-MySQL על מחשב משלו על מנת שלא יצטרך לחלוק ולהתחרות על משאבים עם שרותים אחרים על המחשב (בעיקר Apache שהוא צרכן זכרון ו-I/O לא קטן).
כמו שאר הרכיבים במדריך זה, ההשפעה הגדולה ביותר על ביצועי MySQL היא כמות הזיכרון אשר נקצה ל-Caches & Buffers .
ל-MySQL יש 2 מנועי מידע ראשיים ונפוצים: MyISAM ו- InnoDB. לכל אחד התנהגות שונה וחוזקים שונים. להשוואה קצרה בין ה”מנועים” עברו לקישור הבא: http://dev.mysql.com/tech-resources/articles/storage-engine/part_3.html
מנוע זריז, מתאים בעיקר לאתרים שצריכים לבצע כמות גדולה של “SELECT” ולאו דווקא לעדכן הרבה את תוכן הטבלה. MyISAM משתמש ב-Cache של מערכת ההפעלה כדי לבצע Table Caching, לכן רוב הכיוונונים שיש לעשות לו נוגעים ל Query Caching ו- Index Caching. 2 המשתנים שמשפיעים על הנ”ל הם “key_buffer_size” אשר שולט על גודל ה Index Cache ו-“query_cache_size\query_cache_limit” אשר שולטים על ה Query Caching buffer.
שילוב של הערכים ב-/etc/my.cnf יראה כך:
[mysqld] key_buffer_size = 128M query_cache_size = 32M query_cache_limit = 2M
כדי לעקוב אחרי השפעת הפרמטרים נשתמש בפקודה SHOW STATUS בתוך mysql prompt:
mysql> SHOW STATUS LIKE 'key_read%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Key_read_requests | 837 | | Key_reads | 103 | +-------------------+-------+ 2 rows in set (0.00 sec)
הערך key_read_requests הוא כמות הקריאות ל Table Indexes שהתבצעה מאז עליית המערכת. הערך key_reads הוא כמות השאילתות שבוצעו וניגשו לדיסק (בניגוד ל-Cache) כדי לשלוף את הנתונים. ככל שנעלה את ערך ה-cache, אמור להשתפר היחס של קריאות מה-RAM מול קריאות מהדיסק.
mysql> SHOW STATUS LIKE 'qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 50 | | Qcache_free_memory | 32106552 | | Qcache_hits | 8854 | | Qcache_inserts | 1816 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 65 | | Qcache_queries_in_cache | 631 | | Qcache_total_blocks | 1426 | +-------------------------+----------+ 8 rows in set (0.00 sec)
הערך שעליו יש להסתכל עבור אופטימיזציה עתידית הוא Qcache_lowmem_prunes, אשר אומר מתי היה צריך MySQL למחוק שאילתות מה-cache מכיוון שנגמר לו המקום והיה צריך לפנות שאילתות ישנות לטובת חדשות. עם הערך הנ”ל עולה במהירות, סימן שלא הוקצה מספיק זכרון וסביר שנצטרך להגדיל את הערך query_cache_size. מידע נוסף על הנושא ניתן למצוא בקישור http://www.databasejournal.com/features/mysql/article.php/3110171
בניגוד ל-MyISAM, המנוע InnoDB עושה Caching לא רק לאינדקסים אלא גם למידע מתוך טבלאות, לכן מומלץ להקצות כמות גדולה יותר של RAM ל-MySQL. הערך ששולט על כמות ה-RAM נקרא innodb_buffer_pool_size. בשרת יעודי ל-MySQL מומלץ להקצות עד 70-80 אחוז מה-RAM של המערכת:
[mysqld] innodb_buffer_pool_size = 256M
כדי לעקוב אחרי השימוש של המנוע ב-RAM נשתמש בפקודה:
SHOW INNODB STATUS\G
ערכים נוספים שכדאי לבדוק אך לא ארחיב עליהם במדריך:
בכל ריצה של סקריפט PHP, התוכן של הסקריפט מפוענח (Interpeted) ומקומפל ל opcodes, פקודות ברמה נמוכה.
ברגע שהסקריפט הודר (Compiled) פעם אחת, במידה והוא לא שונה, אין טעם לקמפל אותו שוב. Opcode cachers תופסים את אותו קוד מקומפל ומריצים אותו במקום לקמפל שוב את הסקריפט. ישנם כמה פתרונות, מסחריים וחופשיים אשר מבצעים את העבודה. לא נרחיב על הנושא עוד במדריך זה. להלן רשימה חלקית של PHP Opcode cachers:
גוגל הוא החבר הטוב ביותר שלכם בנושא זה. במדריך זה ניסיתי לרכז מעט מהדברים אשר עשיתי במהלך השנים, תוך הסתמכות והרחבה ע”י מאמרים באינטרנט.