כיצד להגדיר תהליכי Worker ב-Nginx לקבלת ביצועים מרביים

מדריך מעשי להגדרת תהליכי Worker, חיבורים וטיפול באירועים ב-Nginx לקבלת ביצועים מרביים — עם דוגמאות תצורה אמיתיות וטיפים למדידת ביצועים.

קובץ התצורה של Nginx מגיע עם הגדרות ברירת מחדל סבירות. אבל "הגדרות ברירת מחדל סבירות" ו"ביצועים מרביים" הם שני דברים שונים לחלוטין. אם אתם מפעילים שרת אינטרנט עמוס ולא נגעתם בהגדרות תהליכי ה-Worker, כמעט בוודאות אתם מפסידים ביצועים.

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

מדוע הגדרת תהליכי Worker חשובה לכוונון ביצועי Nginx

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

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

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

הגדרת מספר תהליכי Worker הנכון

ההוראה worker_processes בקובץ nginx.conf שולטת בכמה תהליכי Worker Nginx מפעיל. ההמלצה הנפוצה ביותר היא להתאים מספר זה למספר ליבות ה-CPU הזמינות בשרת שלכם.

worker_processes auto;

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

nproc --all

ואז הגדירו זאת במפורש:

worker_processes 4; # לשרת עם 4 ליבות

נקודה חשובה אחת: אם השרת שלכם מוקדש לחלוטין ל-Nginx, התאמת ליבות ל-Workers היא אידיאלית. אם אתם מריצים תהליכים אחרים עתירי CPU לצד Nginx (כמו PHP-FPM, MySQL, או Redis), כדאי להשאיר ליבה או שתיים פנויות כדי למנוע תחרות על משאבים.

כוונון ביצועי Nginx: חיבורי Worker והחשבון מאחוריהם

ההוראה worker_connections קובעת את המספר המרבי של חיבורים בו-זמניים שכל תהליך Worker יכול לטפל בהם. היא נמצאת בתוך בלוק ה-events:

events { worker_connections 1024; }

סך החיבורים המרבי שהשרת שלכם יכול לטפל בהם הוא:

max_connections = worker_processes × worker_connections

כך שרת עם 4 ליבות עם worker_connections 1024 יכול תיאורטית לטפל ב-4,096 חיבורים בו-זמנית. בפועל, תגיעו למגבלות מתאר הקבצים ברמת מערכת ההפעלה לפני שתגיעו לתקרה הזו — וזה מביא אותנו להגדרה הבאה.

הגדלת מגבלת מתאר הקבצים

כל חיבור צורך מתאר קובץ. כברירת מחדל, Linux מגביל זאת ל-1,024 לכל תהליך. אם ה-worker_connections שלכם עולה על כך, תקבלו שגיאות תחת עומס.

הגדירו את המגבלה ב-nginx.conf עם:

worker_rlimit_nofile 65535;

ועדכנו את המגבלות ברמת המערכת ב-/etc/security/limits.conf:

nginx soft nofile 65535 nginx hard nofile 65535

עדכנו גם את /etc/sysctl.conf כדי להגדיל את מגבלת מתאר הקבצים ברמת המערכת כולה:

fs.file-max = 200000

החילו את השינוי עם sysctl -p. שלושת השינויים האלה עובדים יחד — אם תחמיצו אחד מהם, עדיין עלולות להיות כשלים בחיבור תחת עומס גבוה.

זיקה ל-CPU: קיבוע Workers לליבות

כברירת מחדל, מתזמן מערכת ההפעלה מחליט איזו ליבת CPU מריצה כל Worker של Nginx. זה בדרך כלל בסדר, אבל תחת תעבורה גבוהה מאוד תוכלו להפחית החמצות מטמון והחלפות הקשר על ידי קיבוע כל Worker לליבה ספציפית באמצעות worker_cpu_affinity.

# לשרת עם 4 ליבות ו-4 Workers worker_cpu_affinity 0001 0010 0100 1000;

כל מסכת סיביות מתאימה לליבת CPU. ה-Worker הראשון מקובע לליבה 0, השני לליבה 1, וכן הלאה. לשרת עם 8 ליבות ו-8 Workers:

worker_cpu_affinity auto;

הערך auto (זמין ב-Nginx 1.9.10 ומעלה) מטפל בקיבוע באופן אוטומטי. זו האפשרות הנקייה יותר אם אתם משתמשים בגרסת Nginx מודרנית.

כוונון זיקת CPU נוטה להראות את התועלת הגדולה ביותר בשרתים המטפלים ב-10,000+ בקשות בשנייה. מתחת לסף זה, הרווחים בדרך כלל זניחים.

ההוראות Multi-Accept ו-Use

שתי הגדרות נוספות בתוך בלוק ה-events שכדאי להכיר:

events { worker_connections 4096; multi_accept on; use epoll; }

multi_accept on אומר לכל Worker לקבל כמה שיותר חיבורים חדשים במעבר אחד, במקום אחד בכל פעם. זה מפחית זמן תגובה תחת תעבורת פרץ. כמעט תמיד שווה להפעיל זאת.

use epoll מגדיר במפורש את שיטת עיבוד החיבורים ל-epoll, שהיא האפשרות היעילה ביותר ב-Linux. Nginx בדרך כלל בוחר בזה אוטומטית, אבל הגדרה מפורשת לא מזיקה ומתעדת את התצורה שלכם.

חיבורי Keepalive ותפוקת Worker

חיבורי Keepalive מאפשרים לחיבור TCP יחיד לשרת מספר בקשות HTTP. זה מפחית את התקורה של יצירת חיבורים וסגירתם — דבר שחשוב מאוד בקנה מידה גדול.

http { keepalive_timeout 65; keepalive_requests 100; }

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

לאתרים עם תעבורה גבוהה, הגדלת keepalive_requests ל-500 או אפילו 1000 יכולה להפחית משמעותית את תקורת החיבורים. רק שימו לב שזמני keepalive ארוכים מאוד עלולים לתפוס חיבורי Worker עם לקוחות לא פעילים — אז אל תגדירו את keepalive_timeout גבוה מדי (65 שניות כבר נדיב לרוב השימושים).

דוגמה מלאה לכוונון ביצועי Nginx

הנה בלוק תצורה מאוחד שמיישם את כל מה שנסקר לעיל, מתאים לשרת אינטרנט ייעודי עם 4 ליבות:

worker_processes auto; worker_rlimit_nofile 65535; events { worker_connections 4096; multi_accept on; use epoll; } http { keepalive_timeout 65; keepalive_requests 500; sendfile on; tcp_nopush on; tcp_nodelay on; # ... שאר הגדרות ה-http שלכם }

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

כיצד לוודא שהשינויים שלכם עובדים

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

nginx -t

ואז טענו מחדש מבלי לנתק חיבורים:

nginx -s reload

כדי למדוד את ההשפעה, השתמשו ב-wrk או ב-ab (Apache Bench) לסימולציה של עומס מקביל:

# 12 threads, 400 חיבורים במקביל, בדיקה של 30 שניות wrk -t12 -c400 -d30s https://yourdomain.com/

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

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

כאשר כוונון Nginx לבדו אינו מספיק

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

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

לסקירה מעמיקה יותר של אסטרטגיות מטמון שמשלימות את הגדרת Nginx שלכם, ראו כיצד להגדיר מטמון Redis בשרת שלכם מבלי לשבור דבר.

סיכום

כוונון ביצועי Nginx ברמת ה-Worker אינו מסובך, אבל הוא דורש הבנה של מה שכל הוראה עושה בפועל. הגרסה הקצרה: התאימו את worker_processes לליבות ה-CPU שלכם, הגדילו את מגבלות מתאר הקבצים כך שיתאימו ל-worker_connections שלכם, הפעילו multi_accept, והשתמשו ב-epoll. ואז מדדו כדי לאשר שהשינויים מביאים את האפקט שציפיתם לו.

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

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