הגדרת Nginx: תצורה בסיסית ואופטימיזציה

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

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

הגדרת nginx: מה נשבר בתצורת ברירת המחדל

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

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

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

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

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

מה משתנה אחרי תצורה מכוילת של שרת הווב

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

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

משאבי טקסט מגיעים ללקוח בנפח קטן פי 3-4 — העמוד מתחיל להיות מרונדר מוקדם יותר באופן מורגש, והערוץ מפסיק להיות צוואר בקבוק בשיאים.

תורים ומגבלות — זה מה שמגן על ה-backend מקריסה. limit_req ו-limit_conn עם burst ו-nodelay חוסמים את הזינוק בכניסה: בקשות עודפות או ממתינות בתור, או מקבלות סירוב הוגן, במקום להפיל את האפליקציה.

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

ברמת עמידות לתקלות max_fails ו-fail_timeout מוציאים צומת שלא הגיב מהרוטציה ומחזירים אותו לעבודה אוטומטית, וטעינת התצורה מחדש מתבצעת בלי לנתק חיבורים פעילים. את התקרה קובעים worker_connections ומגבלות מערכתיות של descriptors. התוצאה — שיעור הכשלים בזמן שיאים יורד לאפס, וההתאוששות אחרי תקלה אורכת שניות במקום דקות של השבתה.

שלוש גישות להגדרת nginx: עריכה ידנית, תבניות, קוד

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

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

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

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

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

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

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

  1. ביקורת תצורת השרת. אוספים את הקבצים הפעילים, המודולים המופעלים והירושה של פרמטרים, ומצליבים אותם עם לוגי הגישה והשגיאות. בפלט — רשימת צווארי בקבוק עם הערכת השפעה: היכן מטמון התוכן הסטטי הולך לאיבוד, היכן זמני ההמתנה רחבים מדי, והיכן עריכות בוצעו ידנית ולא נכנסו למאגר.
  2. סכימת טיפול בתעבורה. מתעדים מה עומד לפני השרת ואחריו: מאזן עומסים, מטמון חיצוני, אפליקציות, ובאיזה צומת מסתיים ההצפנה. הסכימה מראה אילו כותרות צריך להעביר הלאה והיכן הולכת לאיבוד כתובת הלקוח האמיתית.
  3. טיוטת תצורה. מרכיבים מבנה מקבצים נפרדים לפי דומיין ושירות, ופרמטרים משותפים מוציאים לקובץ אחד שמחובר. מטמון, מגבלות גודל בקשה והפניות מגדירים במפורש, בלי ירושה "מהזיכרון".
  4. בדיקה בסביבת בדיקה. מרימים עותק של הסביבה, מריצים את התצורה בבדיקת תחביר, ואחר כך בתעבורה אמיתית: הפניות מחדש, תוכן סטטי, בקשות לאפליקציה. סביבת הבדיקה תופסת את מה שלא רואים בטקסט הקובץ.
  5. פריסה בלי השבתה. מיישמים טעינה מחדש תוך שמירת חיבורים: תהליכי עבודה חדשים עולים, והישנים מסיימים את הבקשות הנוכחיות. ברגע המעבר לא הולכת לאיבוד אף בקשה, והחזרה לאחור היא החזרת הגרסה הקודמת של הקובץ.
  6. מדידות תחת עומס. משווים מדדים לפני ואחרי: זמן תגובה בתוכן סטטי ובדינמיקה, חלק הבקשות מהמטמון, מספר חיבורים לכל תהליך. המספרים מראים אם נדרש כיוונון עדין נוסף.
  7. מסירת נהלים. התצורות חיות במערכת בקרת גרסאות, עריכה עוברת סביבת בדיקה, ובהיסטוריה נשארים המחבר והסיבה. התורן מקבל הוראה קצרה: איך לבדוק מצב, איך לחזור לאחור, למי לפנות.

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

מה נשאר אצלכם: קובצי תצורה, סכימות ונהלים

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

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

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

מקרה בוחן: פורטל עם תעבורה גבוהה — כשלים וזמן תגובה

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

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

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

כתבנו מחדש את תצורת ה-virtual hosts, והפרדנו בין תוכן סטטי לדינמיקה: תמונות, עיצובים וסקריפטים מגיש ה-proxy עם כותרי מטמון ארוכים, תגובות האפליקציה נשמרות בחוצץ, והחיבורים ל-backend נשמרים קבועים.

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

מה השתנה: סוג הכשל "השרת לא הגיב" נעלם לחלוטין, בשיא המבצע הזמינות נשמרת יציבה, וזמן התגובה באחוזון ה-95 הצטמצם מ-3-4 שניות ל-0.4-0.6.

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

במה שונה פרוקסי הפוך ממאזן עומסים?

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

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

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

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

שאלות טכניות נפוצות לפני תחילת העבודה

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

השבתה בזמן העברת תצורה — עד כמה זה סיכון?

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

האם זה יהיה תואם למה שכבר מותקן אצלנו?

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

יש לנו תצורה משלנו, שכתב קבלן קודם

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

מי יתחזק את זה אחרי המסירה?

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

איך נוודא שהכול עובד?

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

נדבר על המשימה שלכם: מה לשלוח להערכה ולתוכנית

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

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

בנפרד חשוב סדר מסירת הפרויקט: מי מחזיק בהרשאות לשרתים ול-DNS, האם יש חלון לשינויים וסביבת בדיקה שבה עריכות נבדקות לפני הפרודקשן. אחרי זה נחזור עם תוכנית — סדר השינויים ומה בודקים אחרי כל שלב.