Namespaces API מאפשר לכם להפעיל בקלות multitenancy באפליקציה שלכם, פשוט על ידי בחירת מחרוזת של מרחב שמות לכל דייר
ב-appengine_config.py
using the namespace_manager package.
הגדרת מרחב השמות הנוכחי
אפשר לקבל, להגדיר ולאמת מרחבי שמות
using the namespace_manager package.
מנהל מרחב השמות מאפשר להגדיר מרחב שמות נוכחי עבור ממשקי API עם מרחב שמות. אתם מגדירים מראש מרחב שמות נוכחי
ב-appengine_config.py
ומאגרי הנתונים ו-memcache משתמשים אוטומטית במרחב השמות הזה.
רוב המפתחים ב-App Engine ישתמשו בדומיין שלהם ב-Google Workspace (לשעבר G Suite) כמרחב השמות הנוכחי. Google Workspace מאפשרת לכם לפרוס את האפליקציה בכל דומיין שבבעלותכם, כך שתוכלו להשתמש בקלות במנגנון הזה כדי להגדיר מרחבי שמות שונים לדומיינים שונים. אחר כך תוכלו להשתמש במרחבי השמות הנפרדים האלה כדי להפריד בין הנתונים בדומיינים. מידע נוסף זמין במאמר בנושא מיפוי דומיינים מותאמים אישית.
בדוגמת הקוד הבאה מוצג איך להגדיר את מרחב השמות הנוכחי לדומיין Google Workspace ששימש למיפוי כתובת ה-URL. חשוב לציין שהמחרוזת הזו תהיה זהה לכל כתובות ה-URL שממופות דרך אותו דומיין Google Workspace.
כדי להגדיר מרחב שמות ב-Python, משתמשים במערכת ההגדרות של App Engine appengine_config.pyבתיקיית הבסיס של האפליקציה. בדוגמה הפשוטה הבאה מוסבר איך להשתמש בדומיין שלכם ב-Google Workspace כמרחב השמות הנוכחי:
from google.appengine.api import namespace_manager
# Called only if the current namespace is not set.
def namespace_manager_default_namespace_for_request():
# The returned string will be used as the Google Apps domain.
return namespace_manager.google_apps_namespace()
אם לא מציינים ערך ל-namespace, מרחב השמות מוגדר כמחרוזת ריקה. המחרוזת namespace היא שרירותית, אבל היא מוגבלת ל-100 תווים אלפאנומריים, נקודות, קווים תחתונים ומקפים. במילים אחרות, מחרוזות של מרחב שמות צריכות להתאים לביטוי הרגולרי [0-9A-Za-z._-]{0,100}.
לפי המוסכמה, כל מרחבי השמות שמתחילים ב-_ (קו תחתון) שמורים לשימוש המערכת. הכלל הזה במרחב השמות של המערכת לא נאכף, אבל אם לא תפעלו לפיו, יכול להיות שתיתקלו בתוצאות שליליות לא מוגדרות.
מניעת דליפת נתונים
אחד הסיכונים שקשורים בדרך כלל לאפליקציות מרובות דיירים הוא הסכנה שנתונים ידלפו בין מרחבי שמות. דליפות נתונים לא מכוונות יכולות להתרחש ממקורות רבים, כולל:
- שימוש במרחבי שמות עם ממשקי App Engine API שעדיין לא תומכים במרחבי שמות. לדוגמה, ב-Blobstore אין תמיכה במרחבי שמות. אם אתם משתמשים במרחבי שמות עם Blobstore, אתם צריכים להימנע משימוש בשאילתות של Blobstore לבקשות של משתמשי קצה, או במפתחות של Blobstore ממקורות לא מהימנים.
- שימוש באמצעי אחסון חיצוני (במקום Memcache ומאגר נתונים), באמצעות
URL Fetchאו מנגנון אחר, בלי לספק תוכנית חלוקה למרחבי שמות. - הגדרת מרחב שמות על סמך דומיין האימייל של המשתמש. ברוב המקרים, לא רוצים שכל כתובות האימייל בדומיין יוכלו לגשת למרחב שמות. שימוש בדומיין האימייל גם מונע מהאפליקציה שלכם להשתמש במרחב שמות עד שהמשתמש מתחבר.
פריסת מרחבי שמות
בקטעים הבאים מוסבר איך פורסים מרחבי שמות באמצעות כלים וממשקי API אחרים של App Engine.
יצירת מרחבי שמות לכל משתמש בנפרד
חלק מהאפליקציות צריכות ליצור מרחבי שמות על בסיס כל משתמש. אם אתם רוצים להפריד בין נתונים ברמת המשתמש עבור משתמשים מחוברים, כדאי להשתמש ב-
User.user_id()
, שמחזירה מזהה ייחודי וקבוע של המשתמש. בדוגמת הקוד הבאה אפשר לראות איך משתמשים ב-Users API למטרה הזו:
from google.appengine.api import users
def namespace_manager_default_namespace_for_request():
# assumes the user is logged in.
return users.get_current_user().user_id()
בדרך כלל, אפליקציות שיוצרות מרחבי שמות על בסיס כל משתמש מספקות גם דפי נחיתה ספציפיים למשתמשים שונים. במקרים כאלה, האפליקציה צריכה לספק סכימת כתובות URL שקובעת איזה דף נחיתה יוצג למשתמש.
שימוש במרחבי שמות ב-Datastore
כברירת מחדל, Datastore משתמש בהגדרה הנוכחית של מרחב השמות בכלי לניהול מרחבי שמות לבקשות של Datastore. ממשק ה-API מחיל את מרחב השמות הנוכחי על אובייקטים מסוג
Key או Query
כשהם נוצרים. לכן, צריך להיזהר אם אפליקציה מאחסנת אובייקטים של Key או Query בפורמטים סדרתיים, כי מרחב השמות נשמר בסדרות האלה.
אם אתם משתמשים באובייקטים של Key ושל Query שעברו דה-סריאליזציה, ודאו שהם פועלים כמצופה. רוב האפליקציות הפשוטות שמשתמשות ב-Datastore (put/query/get) בלי להשתמש במנגנוני אחסון אחרים יפעלו כמצופה אם תגדירו את מרחב השמות הנוכחי לפני שתקראו ל-Datastore API.
אובייקטים מסוג Query ו-Key מדגימים את ההתנהגויות הייחודיות הבאות בהקשר של מרחבי שמות:
- אובייקטים מסוג
Queryו-Keyיורשים את מרחב השמות הנוכחי כשהם נוצרים, אלא אם מגדירים מרחב שמות מפורש. - כשיישום יוצר
Keyחדש מKeyאב, הKeyהחדש יורש את מרחב השמות שלKeyהאב.
שימוש במרחבי שמות עם Memcache
כברירת מחדל, memcache משתמש במרחב השמות הנוכחי ממנהל מרחבי השמות לבקשות memcache. ברוב המקרים, אין צורך להגדיר במפורש מרחב שמות ב-memcache, ופעולה כזו עלולה לגרום לבאגים לא צפויים.
עם זאת, יש מקרים ייחודיים שבהם כדאי להגדיר במפורש מרחב שמות ב-memcache. לדוגמה, יכול להיות שלאפליקציה שלכם יש נתונים משותפים שמשותפים לכל מרחבי השמות (כמו טבלה שמכילה קודי מדינות).
באמצעות API בשפת Python ל-Memcache, אפשר לקבל את מרחב השמות הנוכחי ממנהל מרחב השמות או להגדיר אותו באופן מפורש כשיוצרים את שירות Memcache. בדוגמה הבאה, מרחב השמות מוגדר באופן מפורש כשמאחסנים ערך ב-memcache:
// Store an entry to the memcache explicitly memcache.add("key", data, namespace='abc')
שימוש במרחבי שמות בתור למשימות
כברירת מחדל, תורים של הודעות Push משתמשים במרחב השמות הנוכחי כפי שהוגדר במנהל מרחבי השמות בזמן יצירת המשימה. ברוב המקרים, אין צורך להגדיר במפורש מרחב שמות בתור המשימות, ופעולה כזו עלולה לגרום לבאגים לא צפויים.
שמות המשימות משותפים לכל מרחבי השמות. אי אפשר ליצור שתי משימות עם אותו שם, גם אם הן משתמשות במרחבי שמות שונים. אם רוצים להשתמש באותו שם משימה למרחבי שמות רבים, פשוט מוסיפים כל מרחב שמות לשם המשימה.
כשמשימה חדשה קוראת לשיטה של תור המשימות
add()
, תור המשימות מעתיק את מרחב השמות הנוכחי ואת הדומיין של Google Workspace (אם רלוונטי) ממנהל מרחבי השמות. כשהמשימה מופעלת, מרחב השמות הנוכחי ומרחב השמות של Google Workspace משוחזרים.
get_namespace() מחזירה ''), אפשר להשתמש בפקודה set_namespace() כדי להגדיר את מרחב השמות הנוכחי למשימה.
יש מקרים ייחודיים שבהם כדאי להגדיר במפורש מרחב שמות למשימה שפועלת בכל מרחבי השמות. לדוגמה, אפשר ליצור משימה שמצברת נתוני שימוש בכל מרחבי השמות. אחר כך אפשר להגדיר במפורש את מרחב השמות של המשימה.
שימוש במרחבי שמות ב-Blobstore
ה-Blobstore לא מפולח לפי מרחב שמות. כדי לשמור על מרחב שמות ב-Blobstore, צריך לגשת ל-Blobstore באמצעות אמצעי אחסון שמודע למרחב השמות (כרגע רק Memcache, מאגר נתונים ותור משימות). לדוגמה, אם ה-Key של Blob מאוחסן בישות Datastore, אפשר לגשת אליו באמצעות Key או Query שמודע למרחב השמות.
אם האפליקציה ניגשת ל-Blobstore באמצעות מפתחות שמאוחסנים באחסון עם מרחב שמות, אין צורך לפלח את Blobstore עצמו לפי מרחב שמות. כדי למנוע דליפות של BLOB בין מרחבי שמות, האפליקציות צריכות:
- לא משתמשים ב-<0x0A><0x0A>
BlobInfo.gql()<0x0A><0x0A> לבקשות של משתמשי קצה. אפשר להשתמש בשאילתות BlobInfo לבקשות אדמיניסטרטיביות (כמו יצירת דוחות על כל ה-blob של האפליקציות), אבל שימוש בהן לבקשות של משתמשי קצה עלול לגרום לדליפות נתונים, כי כל רשומות ה-BlobInfo לא מחולקות לפי מרחב שמות. - לא להשתמש במפתחות Blobstore ממקורות לא מהימנים.
הגדרת מרחבי שמות לשאילתות Datastore
במסוף Google Cloud , אפשר להגדיר את מרחב השמות לשאילתות Datastore.
אם לא רוצים להשתמש בברירת המחדל, בוחרים את מרחב השמות הרצוי מהתפריט הנפתח.
שימוש במרחבי שמות בכלי להעלאה בכמות גדולה
הכלי להעלאה בכמות גדולה תומך בדגל --namespace=NAMESPACE שמאפשר לציין את מרחב השמות שבו רוצים להשתמש. כל מרחב שמות מטופל בנפרד, ואם רוצים לגשת לכל מרחבי השמות, צריך לבצע איטרציה דרכם.
שימוש במרחבי שמות בחיפוש
כשיוצרים מופע חדש של Index, הוא מוקצה למרחב השמות הנוכחי כברירת מחדל:
# set the current namespace
namespace_manager.set_namespace("aSpace")
index = search.Index(name="myIndex")
# index namespace is now fixed to "aSpace"
אפשר גם להקצות מרחב שמות באופן מפורש בבונה:
index = search.Index(name="myIndex", namespace="aSpace")
אחרי שיוצרים מפרט אינדקס, אי אפשר לשנות את מרחב השמות שלו:
# change the current namespace
namespace_manager.set_namespace("anotherSpace")
# the namespaceof 'index' is still "aSpace" because it was bound at create time
index.search('hello')