לדלג לתוכן

איך מיקרוסרביסים מוצאים אחד את השני ברשת

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

למה כתובת קבועה בקוד היא רעיון רע

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

הפתרון - רשם שירותים

הגישה הנפוצה נקראת Service Discovery, ומרכיב מרכזי בה נקרא רשם שירותים, service registry. זה בעצם מסד נתונים מרכזי וזמין תמיד, שמחזיק רשימה עדכנית - איזה שירותים קיימים, ואילו כתובות זמינות עבור כל אחד מהם כרגע. כלים כמו Consul או etcd, וגם מנגנוני DNS פנימיים בקוברנטיס, ממלאים בדיוק את התפקיד הזה.

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

בדיקות תקינות - איך הרשם יודע מה עדיין באמת חי

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

שתי גישות עיקריות - Discovery בצד הלקוח מול בצד השרת

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

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

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

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

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

הצטרפו לקהילה בדיסקורד

לסיכום

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