סביבת זמן הריצה של Python

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

גרסאות Python

‫Python 3.14 משתמש ב-buildpacks. במאמר הזה מפורטת רשימה מלאה של גרסאות Python נתמכות וגרסאות Ubuntu התואמות להן.

כדי להשתמש בגרסת Python נתמכת, צריך:

  • כדי לציין מערכת הפעלה, צריך לכלול את ההגדרות runtime_config ו-operating_system בקובץ app.yaml.

  • מתקינים את גרסה 420.0.0 ואילך של gcloud CLI. כדי לעדכן את כלי ה-CLI, מריצים את הפקודה gcloud components update. כדי לראות את הגרסה המותקנת, מריצים את הפקודה gcloud version.

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

דוגמאות

  • כדי לציין Python 3.14 ב-Ubuntu 24:

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu24"
        runtime_version: "3.14"
    
  • כדי לציין את גרסת Python העדכנית ביותר שנתמכת ב-Ubuntu 24:

      runtime: python
      env: flex
      entrypoint: gunicorn -b :$PORT main:app
    
      runtime_config:
          operating_system: "ubuntu24"
    

מידע נוסף זמין בדף העזרה של app.yaml.

תמיכה בסביבות זמן ריצה אחרות של Python

אם אתם צריכים להשתמש בגרסת Python שלא נתמכת, אתם יכולים ליצור סביבת ריצה בהתאמה אישית ולבחור תמונת בסיס תקינה עם גרסת Python שאתם צריכים.

לגבי תמונות בסיס שסופקו על ידי Google או תמונות בסיס של Docker Python, אפשר לעיין במאמר יצירת סביבות ריצה בהתאמה אישית.

כדי לבדוק לעומק את האפשרות להעביר אפליקציות App Engine ל-Cloud Run באמצעות קונטיינרים, אפשר לעיין במדריך להעברת נתונים.

תלויות

סביבת זמן הריצה מחפשת קובץ requirements.txt בספריית קובצי המקור של האפליקציה ומשתמשת ב-pip כדי להתקין את כל התלות לפני הפעלת האפליקציה. מידע נוסף על הצהרה וניהול של חבילות זמין במאמר שימוש בספריות Python.

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

הפעלת האפליקציה

סביבת זמן הריצה מפעילה את האפליקציה באמצעות entrypoint שמוגדר בקובץ app.yaml. נקודת הכניסה צריכה להתחיל תהליך שמגיב לבקשות HTTP ביציאה שמוגדרת על ידי משתנה הסביבה PORT.

רוב אפליקציות האינטרנט משתמשות בשרת WSGI כמו Gunicorn, ‏ uWSGI או Waitress.

כדי להשתמש באחד מהשרתים האלה, צריך להוסיף אותם כתלות בקובץ requirements.txt של האפליקציה. אם אתם משתמשים ב-gunicorn באפליקציית Flask, ודאו שגרסת Python של האפליקציה תואמת ל-gunicorn.

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

Flask==2.0.2
gunicorn==20.1.0

דוגמה לנקודת כניסה באמצעות gunicorn לאפליקציית Flask:

entrypoint: gunicorn -b :$PORT main:app

דוגמה לנקודת כניסה באמצעות gunicorn לאפליקציית Django:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

Gunicorn הוא שרת WSGI המומלץ, אבל אפשר להשתמש בכל שרת WSGI אחר. לדוגמה, הנה נקודת כניסה שמשתמשת ב-uWSGI עם Flask:

entrypoint: uwsgi --http :$PORT --wsgi-file main.py --callable app

באפליקציות שיכולות לטפל בבקשות בלי שרת WSGI, אפשר פשוט להריץ סקריפט Python:

entrypoint: python main.py

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

entrypoint: gunicorn -c gunicorn.conf.py -b :$PORT main:app

בתיעוד של Gunicorn אפשר לקרוא על כל ערכי ההגדרה של Gunicorn.

עובדים

‫Gunicorn משתמש בתהליכי worker כדי לטפל בבקשות. כברירת מחדל, ‏ Gunicorn משתמש בתהליכי עבודה של סנכרון. הסוג הזה של Worker תואם לכל אפליקציות האינטרנט, אבל כל Worker יכול לטפל רק בבקשה אחת בכל פעם. כברירת מחדל, gunicorn משתמש רק באחד מהעובדים האלה. במקרים כאלה, יכול להיות שהשימוש במופעים לא יהיה יעיל, וזמן האחזור באפליקציות תחת עומס גבוה יתארך.

מומלץ להגדיר את מספר העובדים כך שיהיה גדול פי 2 עד 4 ממספר ליבות ה-CPU במופע, ועוד אחד. אפשר לציין את זה ב-gunicorn.conf.py באופן הבא:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

בנוסף, חלק מאפליקציות האינטרנט שמוגבלות בעיקר על ידי קלט/פלט יכולות ליהנות משיפור בביצועים באמצעות שימוש בסוג אחר של תהליך עבודה. אם מחלקת העובדים שלכם דורשת יחסי תלות נוספים, כמו gevent או tornado, תצטרכו להצהיר על יחסי התלות האלה בקובץ requirements.txt של האפליקציה.

פרוטוקול HTTPS ושרתי proxy להעברה

‫App Engine מפסיק את חיבור ה-HTTPS במאזן העומסים ומעביר את הבקשה לאפליקציה. לרוב האפליקציות לא צריך לדעת אם הבקשה נשלחה באמצעות HTTPS או לא, אבל אפליקציות שצריכות את המידע הזה צריכות להגדיר את Gunicorn כך שיסמוך על ה-proxy של App Engine ב-gunicorn.conf.py:

forwarded_allow_ips = '*'
secure_scheme_headers = {'X-FORWARDED-PROTO': 'https'}

‫Gunicorn יוודא עכשיו ש-wsgi.url_scheme עד 'https', שרוב מסגרות האינטרנט ישתמשו בו כאינדיקציה לכך שהבקשה מאובטחת. אם שרת ה-WSGI או המסגרת לא תומכים בזה, פשוט בודקים את הערך של הכותרת X-Forwarded-Proto באופן ידני.

יש גם אפליקציות שצריכות לזהות את כתובת ה-IP של המשתמש. האפשרות הזו זמינה בכותרת X-Forwarded-For.

שימו לב שההגדרה secure_scheme_headers ב-gunicorn.conf.py צריכה להיות באותיות רישיות, כמו X-FORWARDED-PROTO, אבל הכותרות שהקוד יכול לקרוא יהיו באותיות רישיות וקטנות, כמו X-Forwarded-Proto.

הארכת זמן הריצה

אפשר להשתמש בסביבת זמן הריצה הגמישה של Python כדי ליצור סביבת זמן ריצה בהתאמה אישית. מידע נוסף זמין במאמר בנושא התאמה אישית של Python.

משתני סביבה

משתני הסביבה הבאים מוגדרים על ידי סביבת זמן הריצה:

משתנה סביבה תיאור
GAE_INSTANCE השם של המופע הנוכחי.
GAE_MEMORY_MB נפח הזיכרון שזמין לתהליך האפליקציה.
GAE_SERVICE שם השירות שצוין בקובץ app.yaml של האפליקציה, או אם לא צוין שם שירות, הוא מוגדר כ-default.
GAE_VERSION תווית הגרסה של האפליקציה הנוכחית.
GOOGLE_CLOUD_PROJECT מזהה הפרויקט שמשויך לאפליקציה, שמופיע במסוף Google Cloud
PORT היציאה שתקבל בקשות HTTP.

אפשר להגדיר משתני סביבה נוספים בקובץ app.yaml.

שרת מטא-נתונים

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

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

METADATA_NETWORK_INTERFACE_URL = (
    "http://metadata/computeMetadata/v1/instance/network-interfaces/0/"
    "access-configs/0/external-ip"
)


def get_external_ip():
    """Gets the instance's external IP address from the Compute Engine metadata
    server.

    If the metadata server is unavailable, it assumes that the application is running locally.

    Returns:
        The instance's external IP address, or the string 'localhost' if the IP address
        is not available.
    """
    try:
        r = requests.get(
            METADATA_NETWORK_INTERFACE_URL,
            headers={"Metadata-Flavor": "Google"},
            timeout=2,
        )
        return r.text
    except requests.RequestException:
        logging.info("Metadata server could not be reached, assuming local.")
        return "localhost"