DCSIMG
June 2009 - Posts - מאחורי המסך

מאחורי המסך

משה למפרט, על תכנות מתקדם וביצועים ב-Web.

על הבלוג

עוד חדשות

אתרים שיש לי בהם יד ורגל

June 2009 - Posts

RDP over SSH על יותר ממחשב אחד

English: forcing Windows Vista/7 to save passwords for multiple RDP remote servers using single SSH tunnel.
The solution: using other DNS name/IP for any remote computer.

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

נניח למשל שיש ארבעה מחשבים ברשת, בטווח 192.168.1.x. התחברנו ב-SSH לאחד מהם, והגדנו בו ניתוב פורטים כזה:

192.168.1.1:3389 = port 2001
192.168.1.2:3389 = port 2002
192.168.1.3:3389 = port 2003
192.168.1.4:3389 = port 2004

חיבור בלקוח ה-TS לכתובת localhost:200x יעבוד יופי, אבל ישמור לכולם סט ש"מ/סיסמא בודדים.
עד גירסא 6 של ה-Client, הסיסמא הייתה נשמרת מוצפנת בקובץ. ב-Vista ומעלה, הסיסמא נשמרת ללא קשר לקובץ. התוצאה - סיסמאות היו נשמרות פר כתובת IP וכשמדובר ביותר ממחשב אחד זו בעיה.

הפיתרון: התחברות לכל מחשב דרך כתובת אחרת
127.0.0.1:2001
localhost:2001
fullname.domain.local:2002

ושרת ה-DNS שלכם (או קובץ hosts) יעזור לכם כדי להמשיך עם השיטה.

Posted: Jun 21 2009, 10:42 AM by Moshe L | with no comments
תגים:,

שיפור ביצועים בשרת SQL

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

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

מערכת מסרים

מערכת מסרים טיפוסית נראית ככה:

CREATE TABLE  `pb_messages` (
`m_id` int NOT NULL AUTO_INCREMENT,
  `m_from` int NOT NULL,
  `m_to` int NOT NULL,
  `m_title` varchar(155) NOT NULL DEFAULT '',
  `m_content` text NOT NULL DEFAULT '0',
  `m_new` tinyint NOT NULL DEFAULT '1',
  `m_date` datetime NOT NULL DEFAULT '1987-11-13 00:00:00',
`m_folder` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`m_owner`,`m_id`)
) ;

ב-SQL Server הנפוץ יותר זה יראה קצת אחרת, אבל לא נורא. למעשה מדובר פה בטבלה פשוטה: מספר, אל, מאת, כותרת ותוכן, חדש (בולאני למעשה, למרות שאני העדפתי int), תאריך ותיקיה

נתאר לעצמנו הליך של הכנסת הודעה למנגנון:
יצירת הודעה בדואר נכנס של המשתמש(ים) המקבל(ים)
יצירת הודעה בדואר יוצא של המשתמש השולח

עכשיו נדמיין לעצמנו מנגנון תגובה:
יצירת הודעה בדואר נכנס של המשתמש המקבל(ים?)
יצירת הודעה בדואר נכנס של השולח

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

נחזור לשולחן השרטוט ונבנה עוד שתי טבלאות

CREATE TABLE .`pb_topics` (
  `t_id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`t_id`)
) ;

CREATE TABLE  `pb_links` (
  `l_id` int NOT NULL AUTO_INCREMENT,
  `l_user` int NOT NULL DEFAULT '0',
  `l_new` int NOT NULL DEFAULT '0',
  `l_topic` int NOT NULL DEFAULT '0',
  `l_visible` int NOT NULL DEFAULT '1',
  PRIMARY KEY (`l_id`) );

הודעה חדשה:

יצירת "שרשור" חדש (אני צריך רק את המספר הרציף האוטו')
יצירת הודעה חדשה, עם השרשור
הוספת כל מכותב לרשימת המקבלים

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

כמובן, יש עוד הרבה עבודה: צריך להוסיף אינדקסים לטבלאות על חתכי חיפוש נפוצים, צריך לבנות מנגנון עם טבלת זיכרון כלשהי כדי לשמור למי יש הודעה חדשה (לחסוך I/O יקר) ויש עוד הרבה עבודה כדי שהמערכת תתאים לעומס של ערץ 7 למשל.
חוסרים נוספים שקיימים הם השאילתות לבדיקת מספר ההודעות, שליפת דואר נכנס, שליפת דואר יוצא, הצגת התאריך העברי, התחשבות בהודעות שהמשתמש מחק וכו' שגם שם יש לא מעט עבודה.

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

 

פיתוח מהנה, והרבה הרבה שעות של אופטימיזציה מהנות עוד יותר !

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

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 שונים) היא מורכבת.

 

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