Service Unavailable, וסתם Timeoutים בסביבת ייצור

2 ביוני 2009

3 תגובות

English: Simple ways to find and destroy IIS hangs/timeout's.

אחת התופעות המרגיזות ביותר היא אתר שעובד כהלכה, ללא עומסים חריגים נראים לעין ופתאום זורק שגיאות בסגנון של Server Unavailable, Server too Busy וכו'.
כשמתחברים לשרת, מגלים את אחד משני הדברים:

1. w3wp צורך 100% CPU או קרוב לזה. לחילופין – 100% ממעבד בודד (למשל 50% במקרה של שני מעבדים לוגיים, 25 בארבעה וכו')

2. הכל "מת".
מספר ה-Requestים המעובדים עומד על אפס או קרוב לזה, ה-CPU "ישן" על קרוב ל-0% אבל השרת לא מתפקד.

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

 

100% CPU – הכל תקוע:

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

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

DebugDiag
IIS Diagnostics Toolkit הא כלי לייצור וניתוח Dumpים של IIS. במידה ותפעילו אותו כדקה-שתיים אחרי שהאתר נתקע, תוכלו לקבל ממנו רשימה של Threadים פתוחים, ולכמה זמן הם פתוחים. אם Thread פתוח יותר מדי זמן – סימן שהוא תקוע וכדאי להיפטר ממנו.
טיפ קטן: כדאי לנתח את ה-Dump על מחשב אחר מלבד השרת, הניתוח אורך זמן רב ו"חונק" לאורך זמן את השרת העמוס גם ככה. חבל.

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

 

שרת "מת", אבל ישן

המקרה השני שיכול לקרות הוא שהשרת "מת", אבל לא מציג עומס הגלוי כשמתחברים אליו. במקרה הזה – התקלה היא כנראה ברכיב משנה, ב-95% – מסד נתונים.

נתחיל בלהתחבר לשרת שמחזיק את מסד הנתונים. אצלנו ספציפית עובדים עם MySQL אבל גם ב-SQL Server הנפוץ יותר עם ASP.net הכלים דומים.

mysql:
show full processlist

sql server:
SELECT * FROM MASTER..SysProcesses

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

לא איכנס כאן לעומק הפתרונות שקיימים ברמת SQL (ויש הרבה, ואיכשהו יצא שהתמקצעתי גם בזה),
אבל לעיתים הבעיה היא דווקא ברמת האפליקציה ולאו דווקא ברמת שאילתות SQL, למשל: שימוש ב-ORM כלשהו שמייצר שאילתות לא יעילות או select * from לטבלה עם שדות BLOB או TEXT גדולים, ולעיתים הבעיה היא פשוט Pooling שלא עובד כמו שצריך מסיבות רבות ומגוונות מה שגורם לסתימת ה-Pool.

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

 

נושא הביצועים בתחום ה-Web מורכב הרבה יותר משניתן לתאר, והכרות עמוקה עם התחום הזה, היא חובה של כל ראש צוות ומתכנת. מי שלא מכיר את התחום – חזקה עליו שיכיר אותו בדלית ברירה ועדיף שלא בשעות הלילה המאוחרות.
מבחר הפיתרונות שקיים היום רחב למדיי, והיכולת להתמודד ולהכיר את הפיתרון הטוב ביותר (מה שמנוגד לא אחת לקלות הפיתוח שמבטחיחים רכיבי ASP.NET שונים) היא מורכבת.

 

יש לכם רעיונות? נסיון רלוונטי? שתפו בתגובות ואשמח ללמוד.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

3 תגובות

  1. Avi Pinto2 ביוני 2009 ב 19:49

    אחלה פוסט,

    הקצאת Application Pool נפרד לכל פרוייקט על השרת היא בכלל good practice –
    קודם כל עניין הגבלת הת'רדים לכל אפליקציה,
    והכי חשוב – אם אפליקציה אחת קורסת, היא לא לוקחת את כל השאר איתה שאולה.

    להגיב
  2. martin772 ביוני 2009 ב 21:54

    בדיוק לפני כחודש נתקלתי בבעיה כזו!
    היה webservice אחד, שקרא לרכיב com (ועוד STA) שמשום מה (heap corruption) היה זורק messagebox וכל ה – Application Pool היה נתקע על assert!
    העברתי את ה – WS ל – AppPool אחר עד שתיקנו את רכיב ה – COM (צד שלישי) ומאז הוא לא נפל בכלל.

    כדי למצוא את הבעיה, לקחתי dump של כל ה – iis עם adplus
    adplus.vbs -hang -iis, וחקרתי את ה – dump של w3wp.exe עם DebugDiag.

    המעניין היה, שבגלל שה – IIS שם עבד ב – Webgarden, חלק מהפניות היו מקבלות מענה (ונרשמות בלוג של IIS) וחלק לא.
    בגלל זה לא היה ברור עם השרת עובד – לא עובד, נתקע – לא נתקע.

    לגבי ניתוח הלוג של IIS, אני מעדיף LogParser,
    ואפילו יש כלי חדש ב – codeplex שאני מתכנן לבדוק בהזדמנות:
    http://www.codeplex.com/indihiang

    להגיב
  3. משה3 ביוני 2009 ב 8:36

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

    הסתבר שהודעת השגיאה נזרקה על הקונסול, ואני (המחובר ב-RDP) לא ראיתי אותה עד שהתחברתי עם administrative session (או כמו שזה היה אז – connect to console:1:1).

    במקרה שלך (עד שמתקנים את ה-COM) הייתי שוקל גם לשים Recycle אוטומאטי ל-App Pool כל מספר דקות בודדות – היה מפחית את זמני הקריסות.

    להגיב