מיטוב PHP-FPM לביצועים גבוהים

PHP נמצא בכל מקום וניתן לטעון כי מדובר בשפה המופעלת באופן נרחב באינטרנט.


עם זאת, זה לא בדיוק ידוע ביכולות הביצועים הגבוהות שלו, במיוחד כשמדובר במערכות במקביל מאוד. וזו הסיבה שבמקרים של שימוש מיוחד כזה, שפות כמו צומת (כן, אני יודע, זו לא שפה), גו ואליקסיר משתלטים.

עם זאת, יש המון שאתה יכול לעשות כדי לשפר את ביצועי PHP בשרת שלך. מאמר זה מתמקד בצד ה- php-fpm של הדברים, וזו הדרך הטבעית לקבוע את התצורה בשרת שלך אם אתה משתמש ב- Nginx.

במקרה שאתה יודע מה זה php-fpm, אל תהסס לקפוץ למקטע האופטימיזציה.

מה זה php-fpm?

לא הרבה מפתחים מעוניינים בכך DevOps הצד של הדברים, ואפילו בקרב אלה שכן, מעט מאוד יודעים מה קורה מתחת למכסה המנוע. מעניין, כאשר הדפדפן שולח בקשה לשרת שמריץ PHP, לא PHP הוא המהווה את הנקודה כאיש הקשר הראשון; במקום זאת, זהו שרת HTTP, שהעיקריים שבהם הם אפאצ’י ו- Nginx. אז “שרתי אינטרנט” אלה צריכים להחליט כיצד להתחבר ל- PHP ולהעביר אליו את סוג הבקשה, הנתונים והכותרות..

מחזור התגובה לבקשה במקרה של PHP (קרדיט תמונה: ProinerTech)

ביישומי PHP מודרניים, החלק “מצא קובץ” למעלה הוא index.php, שהשרת מוגדר להאציל את כל הבקשות ל.

עכשיו, כיצד התפתח בדיוק שרת האינטרנט שמתחבר ל- PHP, והמאמר הזה היה מתפוצץ באורך אם היינו נכנסים לכל הנפלאים. אך באופן גס, בתקופה שבה אפאצ’י שלטה כשרת האינטרנט שבחר, PHP היה מודול הכלול בשרת.

כך, בכל פעם שהתקבלה בקשה, השרת יתחיל בתהליך חדש, שיכלול אוטומטית PHP, ויבצע אותו. שיטה זו נקראה mod_php, קיצור של “php כמודול.” לגישה זו היו המגבלות שלה, שגנגקס התגברה עם php-fpm.

ב- php-fpm האחריות לניהול PHP, תהליכים טמונים בתוכנית PHP בתוך השרת. במילים אחרות, לשרת האינטרנט (Nginx, במקרה שלנו), לא אכפת היכן נמצא PHP ואיך הוא נטען, כל עוד הוא יודע לשלוח ולקבל ממנו נתונים. אם אתה רוצה, אתה יכול לחשוב על PHP במקרה זה כשרת אחר בפני עצמו, שמנהל כמה תהליכי PHP לילדים עבור בקשות נכנסות (כך, יש לנו את הבקשה להגיע לשרת, שהתקבל על ידי שרת והועבר לשרת – די משוגע! :-P).

אם ביצעת הגדרות של Nginx, או אפילו סתם חיפשת לתוכם, תיתקל במשהו כזה:

מיקום ~ \ .php $ {
try_files $ uri = 404;
fastcgi_split_path_info ^ (. + \. php) (/.+) $;
fastcgi_pass unix: /run/php/php7.2-fpm.sock;
fastcgi_index index.php;
כולל fastcgi_params;
fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;
}

הקו שאנחנו מעוניינים בו הוא זה: fastcgi_pass unix: /run/php/php7.2-fpm.sock ;, שמורה ל- Nginx לתקשר עם תהליך PHP דרך השקע בשם php7.2-fpm.sock. לכן, עבור כל בקשה נכנסת, Nginx כותב נתונים דרך קובץ זה, ולאחר קבלת הפלט, הוא שולח אותם חזרה לדפדפן.

שוב אני חייב להדגיש שזו לא התמונה השלמה או המדויקת ביותר של המתרחש, אלא שהיא מדויקת לחלוטין עבור רוב משימות ה- DevOps..

בצד זה, נסקור את מה שלמדנו עד כה:

  • PHP לא מקבל ישירות בקשות שנשלחו על ידי הדפדפנים. שרתי אינטרנט כמו Nginx מיירטים תחילה את אלה.
  • שרת האינטרנט יודע להתחבר לתהליך PHP ומעביר את כל נתוני הבקשה (פשוטו כמשמעו מדביק הכל) ל- PHP.
  • כאשר ה- PHP מסיים לעשות את שלו, הוא שולח את התגובה חזרה לשרת האינטרנט, שמחזיר אותה ללקוח (או לדפדפן, ברוב המקרים).

או באופן גרפי:

כיצד PHP ו- Nginx עובדים יחד (קרדיט תמונה: DataDog)

נהדר עד כה, אבל עכשיו מגיעה השאלה של מיליון הדולר: מה בדיוק PHP-FPM?

החלק “FPM” ב- PHP מייצג את “מנהל תהליכים מהיר”, שזו רק דרך מהודרת לומר כי ה- PHP הפועל בשרת אינו תהליך אחד, אלא כמה תהליכי PHP המושרים, בקר ומומתים. על ידי מנהל תהליכים FPM זה. מנהל התהליכים הזה הוא שרת האינטרנט מעביר את הבקשות אליו.

ה- PHP-FPM הוא חור ארנב שלם בפני עצמו, אז תרגישו חופשי לחקור אם תרצו, אך לענייננו, הסבר רב זה יעשה. ��

מדוע לבצע אופטימיזציה של php-fpm?

אז למה לדאוג לכל הריקוד הזה כשדברים עובדים בסדר? למה לא פשוט להשאיר דברים כמו שהם.

למרבה האירוניה, זו בדיוק העצה שאני נותן למרבית מקרי השימוש. אם ההתקנה שלך עובדת מצוין ואין לך מקרי שימוש יוצאי דופן, השתמש בברירות המחדל. עם זאת, אם אתה מעוניין לגדול מעבר למכונה בודדת, אז סחיטת הסכום המקסימלי היא חיונית מכיוון שהיא יכולה לכרות את חשבונות השרת לחצי (או אפילו יותר!).

דבר נוסף שיש להבין הוא ש- Nginx נבנה לטיפול בעומסי עבודה אדירים. הוא מסוגל לטפל באלפי חיבורים בו זמנית, אך אם הדבר אינו נכון להגדרת ה- PHP שלך, אתה פשוט יבזבז משאבים שכן Nginx תצטרך לחכות ל- PHP שיסיים בתהליך הנוכחי ולקבל את בשלב הבא, שליליות סופית את כל היתרונות שנויגקס נבנה לספק!

אז, עם זה מהדרך, בואו נראה מה בדיוק שינינו כשאנחנו מנסים לבצע אופטימיזציה של php-fpm.

כיצד לבצע אופטימיזציה של PHP-FPM?

מיקום קובץ התצורה עבור php-fpm עשוי להיות שונה בשרת, כך שתצטרך לעשות קצת מחקר כדי לאתר אותו. אתה יכול להשתמש בפקודת למצוא אם ב- UNIX. באובונטו שלי הנתיב הוא /etc/php/7.2/fpm/php-fpm.conf. ה- 7.2 הוא כמובן גרסת ה- PHP אותה אני מריץ.

כך נראים השורות הראשונות בקובץ זה:

;;;;;;;;;;;;;;;;;;;;;;;
; תצורת FPM;
;;;;;;;;;;;;;;;;;;;;;;;

; כל הנתיבים היחסיים בקובץ תצורה זה הם יחסית להתקנת PHP
; קידומת (/ usr). ניתן לשנות קידומת זו באופן דינמי באמצעות
; טיעון ‘-p’ משורת הפקודה.

;;;;;;;;;;;;;;;;;;;;
; אופציות גלובליות;
;;;;;;;;;;;;;;;;;;;;

[גלובלי]
; קובץ pid
; הערה: קידומת ברירת המחדל היא / var
; ערך ברירת מחדל: אין
pid = /run/php/php7.2-fpm.pid

; קובץ יומן שגיאות
; אם זה מוגדר "syslog", יומן נשלח ל- syslogd במקום להיכתב
; לקובץ מקומי.
; הערה: קידומת ברירת המחדל היא / var
; ערך ברירת מחדל: log / php-fpm.log
error_log = /var/log/php7.2-fpm.log

כמה דברים צריכים להיות גלויים מייד: השורה pid = /run/php/php7.2-fpm.pid מגלה לנו איזה קובץ מכיל את מזהה התהליך של תהליך php-fpm.

אנו רואים גם ש- /var/log/php7.2-fpm.log הוא המקום בו php-fpm הולך לאחסן את היומנים שלו.

בתוך קובץ זה, הוסף עוד שלושה משתנים כאלה:

emergency_restart_threshold 10
emergency_restart_interval 1 מטר
process_control_timeout 10s

שתי ההגדרות הראשונות זהירות ואומרות על תהליך php-fpm שאם עשרה תהליכי ילד נכשלים תוך דקה, על תהליך php-fpm הראשי להפעיל מחדש את עצמו.

זה אולי לא נשמע חזק, אבל PHP הוא תהליך קצר מועד, שגורם לזליגת זיכרון, כך שהפעלה מחדש של התהליך העיקרי במקרים של כשל גבוה יכולה לפתור הרבה בעיות.

האפשרות השלישית, process_control_timeout, אומרת לילד התהליכים להמתין לזמן כה רב לפני שהוא מבצע את האות שהתקבל מתהליך ההורה. זה שימושי במקרים בהם התהליכים של הילד נמצאים באמצע משהו כאשר תהליכי ההורה שולחים אות KILL, למשל. עם עשר שניות ביד, יהיה להם סיכוי טוב יותר לסיים את המשימות שלהם ולצאת בחן.

באופן מפתיע, זה לא הבשר של תצורת php-fpm! הסיבה לכך היא להגשת בקשות אינטרנט, ה- php-fpm יוצר מאגר תהליכים חדש, שיהיה לו תצורה נפרדת. במקרה שלי, שם הבריכה התגלה כ- www והקובץ שרציתי לערוך היה /etc/php/7.2/fpm/pool.d/www.conf.

בוא נראה איך קובץ זה מתחיל:

; התחל בריכה חדשה בשם ‘www’.
; ניתן להשתמש במאגר $ המשתנה בכל הנחיה ויוחלף על ידי
; שם הבריכה (‘www’ כאן)
[www]

; לפי קידומת בריכה
; זה חל רק על ההוראות הבאות:
; – ‘access.log’
; – ‘slowlog’
; – ‘האזנה’ (unixsocket)
; – ‘chroot’
; – ‘צ’דיר’
; – ‘php_values’
; – ‘php_admin_values’
; כאשר לא מוגדרת, הקידומת הגלובלית (או / usr) חלה במקום.
; הערה: הנחיה זו יכולה להיות יחסית גם לקידומת הגלובלית.
; ערך ברירת מחדל: אין
קידומת = / נתיב / אל / בריכות / $ בריכה

; Unix משתמש / קבוצת תהליכים
; הערה: המשתמש חובה. אם הקבוצה אינה מוגדרת, קבוצת המשתמש המוגדרת כברירת מחדל
; יהיה בשימוש.
user = www-data
group = www-data

מבט מהיר בסוף קטע הקוד למעלה פותר את החידה מדוע תהליך השרת פועל כ- www-data. אם נתקלת בבעיות בהרשאת קבצים בעת הגדרת אתר האינטרנט שלך, סביר להניח ששינית את הבעלים או הקבוצה של הספרייה ל- www-data, ובכך לאפשר לתהליך PHP להיות מסוגל לרשום קבצי יומן ולהעלות מסמכים וכו ‘..

לבסוף, אנו מגיעים למקור העניין, הגדרת מנהל התהליכים (בערב). באופן כללי, תראה את ברירת המחדל כדבר כזה:

pm = דינמי
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200

אז מה “דינמי“הכוונה כאן? אני חושב שהמסמכים הרשמיים הכי מסבירים את זה (זאת אומרת, זה אמור להיות חלק מהקובץ שאתה עורך, אבל אני שכבתי אותו כאן למקרה שזה לא יהיה):

; בחר כיצד מנהל התהליכים ישלוט על מספר התהליכים בילדים.
; ערכים אפשריים:
; סטטי – מספר קבוע (pm.max_children) של תהליכים בילדים;
; דינמי – מספר התהליכים בילדים מוגדרים באופן דינמי על בסיס
; בעקבות הוראות. עם ניהול תהליכים זה, יהיו
; תמיד לפחות ילד אחד.
; pm.max_children – המספר המרבי של ילדים שיכולים
; להיות חי באותו הזמן.
; pm.start_servers – מספר הילדים שנוצרו בעת ההפעלה.
; pm.min_spare_servers – המספר המינימלי של ילדים ב- ‘סרק’
; מצב (מחכה לעיבוד). אם המספר
; של תהליכים ‘סרק’ הוא פחות מזה
; מספר ואז ילדים ייווצרו.
; pm.max_spare_servers – המספר המרבי של ילדים ב- ‘סרק’
; מצב (מחכה לעיבוד). אם המספר
; של תהליכים ‘סרק’ גדול מזה
; המספר ואז ילדים מסוימים ייהרגו.
; ondemand – אין ילדים נוצרים בעת ההפעלה. ילדים יקבלו מזלג מתי
; בקשות חדשות יתחברו. נעשה שימוש בפרמטר הבא:
; pm.max_children – המספר המרבי של ילדים זה
; יכול להיות חי באותו הזמן.
; pm.process_idle_timeout – מספר השניות שלאחריו
; תהליך סרק ייהרג.
; הערה: ערך זה הוא חובה.

אז אנו רואים שיש שלושה ערכים אפשריים:

  • סטטי: מספר קבוע של תהליכי PHP יישמר לא משנה מה.
  • דינמי: אנו מקבלים ציון המינימום והמספר המרבי של תהליכים ש- php-fpm ישארו בחיים בכל נקודת זמן נתונה.
  • לפי דרישה: תהליכים נוצרים ונחרבים, ובכן, לפי דרישה.

אז איך הגדרות אלה חשובות?

במילים פשוטות, אם יש לך אתר עם תנועה נמוכה, ההגדרה “דינאמית” מבזבזת משאבים רוב הזמן. בהנחה שיש לכם pm.min_spare_servers מוגדרים ל -3, שלושה תהליכי PHP ייווצרו וישמרו גם כשאין תנועה באתר. במקרים כאלה, “ondemand” היא אפשרות טובה יותר, ומאפשרת למערכת להחליט מתי להתחיל תהליכים חדשים.

מצד שני, אתרים העוסקים בכמויות גדולות של תנועה או חייבים להגיב במהירות ייענשו בהגדרה זו. יצירת תהליך PHP חדש, הפיכתו לחלק מהבריכה ומעקב אחריו, היא תקורה נוספת אשר עדיף להימנע ממנה.

באמצעות pm = סטטי מתקן את מספר התהליכים בילדים, ומאפשר להשתמש במשאבי המערכת המרביים להגשת הבקשות ולא לניהול PHP. אם אתה הולך במסלול זה, היזהר שיש לו את ההנחיות והממצאים שלו. מאמר צפוף למדי אך שימושי ביותר בנושא כאן.

מילים אחרונות

מכיוון שמאמרים על ביצועי רשת יכולים להצית מלחמות או לבלבל אנשים, אני מרגיש שכמה מילים מסודרות לפני שאנחנו סוגרים את המאמר הזה. כוונון הביצועים עוסק באותה מידה בניחושים ואומנויות אפלה כמו בידע במערכת.

אפילו אם אתה יודע בעל פה את כל הגדרות ה- php-fpm, ההצלחה אינה מובטחת. אם לא היה לך מושג לגבי קיומו של php-fpm, אינך צריך לבזבז זמן לדאוג בקשר לזה. פשוט תמשיך לעשות את מה שאתה כבר עושה והמשיך.

במקביל, הימנע מסוף היותך נרקומני ביצועים. כן, אתה יכול להשיג ביצועים טובים עוד יותר על ידי קומפילציה של PHP מאפס והסרת כל המודולים שלא תשתמש בהם, אך גישה זו אינה מספיק שפוטית בסביבות ייצור. כל הרעיון של אופטימיזציה של משהו הוא לבדוק האם הצרכים שלך נבדלים מהברירות המחדל (מה שהם עושים לעתים רחוקות!), ולבצע שינויים קלים לפי הצורך.

אם אינך מוכן לבזבז זמן על אופטימיזציה של שרתי PHP שלך, תוכל לשקול למנף פלטפורמה אמינה כמו קינסטה שדואגים למיטוב ביצועים ואבטחה.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map