• בלוג
  • חיבור מספר שרתי GraphQL עם Bramble

חיבור מספר שרתי GraphQL עם Bramble

לפי האתר שלהם, בראמבל הם Production Ready GraphQL Federation. מאחר ואני תמיד שמח לבדוק חלופות פשוטות יותר ל Apollo הלכתי לבנות פרויקט דוגמה קטן עם בראמבל. קוד הפרויקט כאן: https://github.com/ynonp/playing-with-bramble

בפוסט אספר איך ברמבל עובד ומתי שווה לשקול אותו.

1. מה זה אומר GraphQL Federation

נניח שיש לכם מספר סרביסים שכל אחד מהם עובד ב GraphQL, ואתם רוצים לחשוף רק ממשק אחד לאפליקציית ה Front End שדרכו האפליקציה תוכל למשוך מידע מכל הסרביסים. במצב כזה אתם תרצו לבנות סרביס אחד שנקרא GraphQL Gateway שישתמש בסכימה שתהיה סוג-של-חיבור של כל הסכימות מכל הסרביסים, וכל פעם שנבקש ממנו מידע הוא פשוט יפנה לסרביס המתאים לקבל ממנו את המידע.

שתי הדרכים המרכזיות לחבר סכימות נקראות Schema stitching ו Federation כשההבדלים המרכזיים נוגעים לאופן שבו אנחנו מתיחסים לטיפוסים המשותפים בין סרביסים, ולאיך ממזגים את הסכימות. אומנם ברמבל הם פיתרון מסוג Federation אבל בפרויקט הדוגמה שכתבתי לא הגעתי לחלקים המעניינים של ה Federation של מיזוג טיפוסים ולכן לפחות מבחינת מה שנראה בפוסט הם היו יכולים באותה מידע לקרוא לזה Schema Stiching. מה שחשוב להבין כאן זה ש Bramble יהיה סוג של Gateway אוטומטי שפשוט מקבל את הסרביסים ויודע להעביר בקשות ולחבר מידע משניהם. ומה שאהבתי בו זה שהסטאפ היה מאוד מאוד פשוט.

2. הקמת שרת Bramble

כל מה שצריך בשביל להרים שרת Bramble הוא להריץ את הבינארי (כתוב ב go) ולהעביר לו קובץ קונפיגורציה שאומר איפה הסרביסים שהוא צריך לחבר. קובץ הקונפיגורציה שאני כתבתי נראה כך:

{
  "services": [
    "http://tasks-server:3000/graphql",
    "http://fortune:3000/graphql"
  ],
  "plugins": [
    {
      "name": "playground"
    }
  ]
}

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

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

type Query {
  fortune: String!
  service: Service!
}

type Service {
  name: String! # unique name for the service
  version: String! # any string
  schema: String! # the full schema for the service
}

והחלק הרלוונטי בסכימה מסרביס המשימות נראה כך:

type Query {
  tasks(done: Boolean): [Task]
  task(id: String): Task
  service: Service!
}

type Service {
  name: String! # unique name for the service
  version: String! # any string
  schema: String! # the full schema for the service
}

גם ה Resolver עבור Service הוא די העתק-הדבק מהדוגמאות שלהם. הנה אחד שכתבתי לדוגמה בסרביס המשימות:

service(_obj, _args, _context, info) {
    return {
        name: 'Tasks',
        version: '1.0',
        schema: require('./schema.graphql'),
    }
},

ובסך הכל זה כל מה שצריך בשביל שבראמבל יעבוד.

3. איך בראמבל עובד

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

$ docker-compose up

ואחרי זה כנסו בדפדפן ל localhost:8082/playground.

אחרי זה תוכלו להריץ שאילתה כמו זו:

query a{
  tasks {
    text
  }
}

ולקבל את רשימת המשימות או שאילתה כזו:

query b{
  fortune
}

כדי לקבל fortune אקראי.

זה מדליק כי שתי השאילתות הולכות לאותו Gateway והוא כבר יודע לשלוח את השאילתה הראשונה לסרביס המשימות ואת השניה לסרביס ה fortune.

באותו Playground אפשר לראות גם את הסכימה המחוברת ובלוק Query שלה נראה כך:

type Query {
  tasks(done: Boolean): [Task]
  task(id: String): Task
  fortune: String!
}

כלומר הוא חיבור של ה Query משני הסרביסים. את כל זה בראמבל הצליח לעשות אוטומטית.

4. מה עדיין לא הצלחתי לעשות

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

בינתיים מה שאהבתי בפרויקט:

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

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

  3. התקנה פשוטה דרך דוקר (בניתי אימג' בעצמי - האימג' שלהם לא עבד).

  4. תמיכה מובנית באימות זהות דרך JWT

מה שלא אהבתי בפרויקט היה:

  1. אין מספיק דוגמאות וגם התיעוד לא מקיף במיוחד.

  2. ה Docker Image שהם מספקים לא עבד.

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

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

זה הלינק לגיטהאב של בראמבל: https://github.com/movio/bramble

וזה פרויקט הדוגמה שלי שמשתמש בו עם שני סרביסים הכתובים ב Node.JS: https://github.com/ynonp/playing-with-bramble