# המסע של Shoprocket למיקרו-שירותים, חלק 1: במה טעיתי כשפירקתי את המונוליט

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

Winston Berty  - 17 במרץ 2016 - 5 דקות קריאה

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

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

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

## מה חשבתי שמיקרו-שירותים הם

אין הגדרה רשמית למיקרו-שירותים, אבל ממה שקראתי הבנתי שארכיטקטורת מיקרו-שירותים היא דרך לתכנן אפליקציות תוכנה כמערכות מבוזרות של שירותים עצמאיים, כל אחד מתמחה מאוד ובעל מחזור חיים משלו. להקדמה מפורטת, ה[מאמר](https://martinfowler.com/articles/microservices.html) של מרטין פאולר מצוין.

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

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

## האתגר הראשון היה אנושי, לא טכני

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

במבט לאחור, זו הייתה בחירה גרועה לשירות ראשון. המוצר שלנו כולל ווידג'ט JavaScript ש[מאפשר מסחר אלקטרוני בכל אתר](https://v3.shoprocket.io/he/features/sell-on-any-website.md). אנחנו מתייחסים ל-sessions כאל משאב, ושומרים את מידע ה-session במסד הנתונים כדי לנתח נטישת עגלות ומדדים אחרים. אבל המשאב הזה פחות מוחשי מדברים כמו הזמנות או שורות הזמנה, והשתמשנו ב-sessions כמעט בכל שינוי במצב האפליקציה. זה אומר שהשירות בהכרח ידבר המון עם שאר האפליקציה, דבר שלא צפיתי ושהקשה על המשימה שלי.

## מה למדתי כשבניתי אותו בפועל

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

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

לא פעלתי לפי העצה הזאת. להוט לבנות רכיב משלי, המשכתי עם שירות ה-sessions.

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

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

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

## ההערכה הכנה

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

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

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

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

Shoprocket תמשיך במסע שלה. בחלק 2 זה נהיה מעניין יותר.

---

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

---

- HTML version: https://v3.shoprocket.io/he/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith
- Language: עברית (he)
- Also in: [العربية](https://v3.shoprocket.io/ar/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Deutsch](https://v3.shoprocket.io/de/blog/shoprocket-microservices-teil-1-monolith-zerlegen-fehler.md), [Ελληνικά](https://v3.shoprocket.io/el/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [English](https://v3.shoprocket.io/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Español](https://v3.shoprocket.io/es/blog/shoprocket-microservicios-parte-1-lo-que-hice-mal-monolito.md), [Français](https://v3.shoprocket.io/fr/blog/shoprocket-vers-les-microservices-partie-1-decouper-le-monolithe.md), [हिन्दी](https://v3.shoprocket.io/hi/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Bahasa Indonesia](https://v3.shoprocket.io/id/blog/perjalanan-shoprocket-menuju-microservices-bagian-1-salah-memecah-monolit.md), [Italiano](https://v3.shoprocket.io/it/blog/viaggio-di-shoprocket-verso-i-microservizi-parte-1-cosa-ho-sbagliato-sul-monolite.md), [日本語](https://v3.shoprocket.io/ja/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Lietuvių](https://v3.shoprocket.io/lt/tinklarastis/shoprocket-kelione-i-mikropaslaugas-1-dalis.md), [Norsk](https://v3.shoprocket.io/nb/blogg/shoprockets-vei-mot-mikrotjenester-del-1-hva-jeg-tok-feil-av.md), [Nederlands](https://v3.shoprocket.io/nl/blog/shoprocket-microservices-deel-1-monoliet-opknippen.md), [Polski](https://v3.shoprocket.io/pl/blog/droga-shoprocket-do-mikroserwisow-czesc-1-rozbijanie-monolitu.md), [Português](https://v3.shoprocket.io/pt/blog/jornada-do-shoprocket-para-microsservicos-parte-1-o-que-errei-ao-quebrar-o-monolito.md), [Română](https://v3.shoprocket.io/ro/blog/drumul-shoprocket-spre-microservicii-partea-1-ce-am-gresit-cu-monolitul.md), [Русский](https://v3.shoprocket.io/ru/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [ไทย](https://v3.shoprocket.io/th/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Türkçe](https://v3.shoprocket.io/tr/blog/shoprocket-mikroservis-yolculugu-1-monoliti-parcalarken-yanlis-yaptiklarim.md), [中文](https://v3.shoprocket.io/zh/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md)
