בדף הזה מוסבר איך להעביר את סביבות הריצה של Java מהדור הראשון לדור השני. כדי לשדרג את האפליקציה מהדור השני לגרסה העדכנית ביותר של Java שנתמכת, אפשר לעיין במאמר בנושא שדרוג אפליקציה קיימת.
Java 8 יצא משימוש. לא תוכלו לפרוס אפליקציות Java 8, גם אם הארגון שלכם השתמש בעבר במדיניות ארגונית כדי להפעיל מחדש פריסות של סביבות ריצה מדור קודם. האפליקציות הקיימות שלכם ב-Java 8 ימשיכו לפעול ולקבל תנועה. מומלץ לעבור לגרסה העדכנית ביותר של Java שנתמכת.
מעבר לזמני הריצה של Java מהדור השני מאפשר לכם להשתמש בתכונות שפה עדכניות ולבנות אפליקציות ניידות יותר עם קוד אידיומטי.
הסבר על אפשרויות ההעברה
כדי לצמצם את המאמץ והמורכבות של המעבר בזמן הריצה, סביבת App Engine standard מאפשרת לכם לגשת להרבה שירותים וממשקי API מדור קודם, כמו Memcache, בזמן הריצה של Java מהדור השני. אפליקציית Java יכולה לקרוא לממשקי ה-API של השירותים הכלולים דרך ה-JAR של App Engine API, ולקבל גישה לרוב היכולות כמו בסביבת זמן הריצה של Java 8.
יש לכם גם אפשרות להשתמש ב Google Cloud מוצרים שמציעים פונקציונליות דומה לזו של חבילות השירותים הקודמות. המוצרים האלה מספקים ספריות לקוח של Java ב-Cloud שמתאימות לשימוש בשפה. Google Cloud לגבי חבילות השירותים שלא זמינות כמוצרים נפרדים ב-Google Cloud, כמו עיבוד תמונות, חיפוש והודעות, אפשר להשתמש בספקים של צד שלישי או בפתרונות עקיפים אחרים.
מידע נוסף על מעבר לשירותים לא משולבים זמין במאמר מעבר משירותים משולבים.
יש כמה הבדלים באופן שבו מבצעים את ההעברה בזמן הריצה, בהתאם לבחירה אם להשתמש בשירותים הקודמים בחבילה:
| מעבר לסביבות זמן ריצה של Java מדור שני עם שירותים בחבילה | מעבר לזמני ריצה של Java מדור שני בלי שירותים בחבילה |
|---|---|
| גישה לשירותים בחבילה באמצעות קובץ ה-JAR של App Engine APIs. | אפשר גם להשתמש ב מוצרים מומלצים Google Cloud או בשירותים של צד שלישי. |
|
משתמשים ב-
יכול להיות שתצטרכו להגדיר גם קובצי YAML נוספים, בהתאם לתכונות שבהן האפליקציה משתמשת. |
משתמשים ב-
יכול להיות שתצטרכו להגדיר גם קובצי YAML נוספים, בהתאם לתכונות שבהן האפליקציה משתמשת. |
| הפריסה של האפליקציות מתבצעת באמצעות Jetty. משתמשים בפורמט WAR כדי לארוז את האפליקציה. | הפריסה של האפליקציות מתבצעת באמצעות השרת שלכם. משתמשים בפורמט JAR כדי לארוז את האפליקציה. כדי לקבל מידע נוסף על המרת קובץ WAR קיים ל-JAR שניתן להפעלה, אפשר לעיין במאמר בנושא אריזה מחדש של קובץ WAR. |
סקירה כללית של תהליך המיגרציה
בהמשך מפורטים כמה שינויים שאולי תצטרכו לבצע באפליקציית Java 8 הקיימת שלכם ב-App Engine ובתהליך הפריסה כדי להשתמש בסביבות זמן הריצה של Java מהדור השני:
- מורידים את Google Cloud CLI.
- להעביר את התוסף העצמאי של App Engine Maven אל התוסף של Maven שמבוסס על CLI של gcloud או אל התוסף של Gradle שמבוסס על CLI של gcloud.
- אם אתם משתמשים בשירותים הקודמים בחבילה, צריך להתקין את App Engine API JAR.
ההבדלים העיקריים בין Java 8 לבין סביבות זמן הריצה של Java מהדור השני
בטבלה הבאה מפורטים ההבדלים בין Java 8 לבין סביבות זמן הריצה של Java מהדור השני בסביבת App Engine סטנדרטית:
| זמן ריצה של Java 8 | סביבות זמן ריצה של Java מהדור השני | |
|---|---|---|
| פריסת השרת | השרת נפרס בשבילכם באמצעות Jetty | אם האפליקציה שלכם לא משתמשת בשירותים הישנים בחבילה, תצטרכו לפרוס שרת בעצמכם.1 |
| שירותים מדור קודם בחבילה של App Engine | מסופק | מסופק |
| אפשרות להשתמש בספריות לקוח של Cloud ל-Java | כן | כן |
| תמיכה בתוסף שפה ובספריית המערכת | כן | כן |
| גישה לרשת חיצונית | כן | כן |
| גישה למערכת הקבצים | גישת קריאה/כתיבה אל /tmp
|
גישת קריאה/כתיבה אל /tmp
|
| שפת זמן הריצה | הותאם ל-App Engine | זמן ריצה של קוד פתוח ללא שינויים |
| מנגנון בידוד | ארגז חול לקונטיינרים מבוסס gVisor | ארגז חול לקונטיינרים מבוסס gVisor |
| בדיקה באמצעות שרת פיתוח מקומי | נתמך | נתמך |
| הגדרת thread safety | אפשר לציין את הגרסה בקובץ appengine-web.xml.
|
אי אפשר לציין את ההגדרה הזו בקובצי התצורה. כל האפליקציות נחשבות בטוחות לשימוש עם שרשורים.3 |
| רישום ביומן | משתמשים ב-java.util.logging.ConsoleHandler, שכותב ל-stderr ומרוקן את הזרם אחרי כל רשומה. |
Cloud Logging רגיל 2 |
| תמיכה בפלאגין DataNucleus בגרסה 2.x | נתמך | לא אפשרי 4 |
הערות:
אם האפליקציה לא משתמשת בשירותים הקודמים שצורפו, סביבות זמן הריצה של Java מהדור השני יכולות להריץ כל מסגרת Java, כל עוד אורזים שרת אינטרנט שמוגדר להגיב לבקשות HTTP ביציאה שצוינה במשתנה הסביבה
PORT(מומלץ) או ביציאה 8080. לדוגמה, בסביבות זמן הריצה של Java מהדור השני אפשר להריץ קובץ Spring Boot Uber JAR כמו שהוא. דוגמאות נוספות מופיעות בקטע גמישות של מסגרות.אם האפליקציה שלכם משתמשת בשירותים הקודמים בחבילה, App Engine פורס אותה באמצעות Jetty באותו אופן כמו בסביבת זמן הריצה של Java 8.
הרישום ביומן בזמני הריצה של Java מדור שני מתבצע לפי תקן הרישום ביומן ב-Cloud Logging. בזמן הריצה של Java מהדור השני, יומני האפליקציות כבר לא מצורפים ליומני הבקשות, אלא מופרדים ברשומות שונות. מידע נוסף על קריאה וכתיבה של יומנים בסביבות זמן הריצה של Java מהדור השני זמין במדריך לרישום ביומן.
כדי להגדיר אפליקציה לא בטוחה לשימוש עם שרשור (non-threadsafe) בסביבת זמן הריצה של Java מהדור השני, בדומה להגדרה של
<threadsafe>false</threadsafe>ב-Java 8, צריך להגדיר את הערך של max concurrency ל-1 בקובץapp.yamlאו בקובץappengine-web.xmlאם משתמשים בשירותים מדור קודם שצורפו.Google לא תומכת בספריית DataNucleus בסביבות זמן הריצה מהדור השני. גרסאות חדשות יותר של DataNucleus לא תואמות לאחור לגרסאות שבהן נעשה שימוש ב-Java 8. כדי לגשת ל-Datastore, מומלץ להשתמש בספריית לקוח במצב Datastore או בפתרון Java Objectify (גרסה 6 ואילך). Objectify הוא API קוד פתוח ל-Datastore שמספק רמת הפשטה גבוהה יותר.
הבדלים בשימוש בזיכרון
בזמן ריצה מדור שני, השימוש בזיכרון גבוה יותר בהשוואה לזמן ריצה מדור ראשון. הסיבות לכך יכולות להיות מגוונות, למשל גרסאות שונות של תמונות בסיס והבדלים באופן שבו שני הדורות מחשבים את השימוש בזיכרון.
בסביבות זמן ריצה מהדור השני, השימוש בזיכרון של מופע מחושב כסכום של מה שתהליך האפליקציה צורך, ומספר קובצי האפליקציה שנשמרים באופן דינמי במטמון בזיכרון. כדי למנוע מצב שבו אפליקציות שדורשות הרבה זיכרון גורמות להשבתת מופעים בגלל חריגה ממגבלות הזיכרון, כדאי לשדרג לסוג מופע גדול יותר עם יותר זיכרון.
הבדלים בשימוש במעבד
בזמן הפעלה מדור שני, יכול להיות שיהיה שימוש בסיסי גבוה יותר במעבד כשמפעילים מופע. בהתאם להגדרת קנה המידה של האפליקציה, יכולות להיות לכך תופעות לוואי לא רצויות, כמו מספר מופעים גבוה מהצפוי אם האפליקציה מוגדרת להרחבה על סמך ניצול המעבד. כדי להימנע מהבעיה הזו, כדאי לבדוק את הגדרות קנה המידה של האפליקציה ולוודא שמספר המופעים מקובל.
הבדלים בכותרות הבקשות
סביבות זמן ריצה מהדור הראשון מאפשרות להעביר לאפליקציה כותרות של בקשות עם קווים תחתונים (לדוגמה, X-Test-Foo_bar). בזמן ריצה מדור שני, Nginx מוצג בארכיטקטורת המארח. כתוצאה מהשינוי הזה, סביבות זמן ריצה מהדור השני מוגדרות להסרה אוטומטית של כותרות עם קווים תחתונים (_). כדי למנוע בעיות באפליקציה, מומלץ להימנע משימוש בקווים תחתונים בכותרות של בקשות באפליקציה.
גמישות המסגרת
סביבות זמן הריצה של Java מהדור השני לא כוללות מסגרת להצגת תוכן באינטרנט, אלא אם אתם משתמשים בשירותים מדור קודם שצורפו לחבילה. המשמעות היא שאפשר להשתמש במסגרת שאינה מבוססת על סרוולט. אם אתם משתמשים בחבילת השירותים מדור קודם, סביבות זמן הריצה של Java מהדור השני מספקות את מסגרת Jetty להצגת אינטרנט.
יש hello world דוגמאות לשימוש במסגרות פופולריות של Java לאינטרנט במאגרGoogle Cloud GitHub:
העברה של קובצי XML לפורמטים של קובצי YAML
ה-CLI של gcloud לא תומך בפורמטים הבאים של קבצים:
cron.xmldatastore-index.xmldispatch.xmlqueue.xml
בדוגמאות הבאות מוסבר איך להעביר קובצי xml לקובצי yaml.
העברת הקבצים באופן אוטומטי
כדי להעביר את קובצי xml באופן אוטומטי:
צריך לוודא שמותקנת גרסה 226.0.0 ואילך של ה-CLI של gcloud. כדי לעדכן לגרסה האחרונה:
gcloud components updateלכל קובץ שרוצים להעביר, מציינים אחת מהפקודות המשניות הבאות (
cron-xml-to-yaml, datastore-indexes-xml-to-yaml,dispatch-xml-to-yaml, queue-xml-to-yaml) ואת שם הקובץ:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xmlלפני שפורסים את הקובץ המומר בסביבת הייצור, כדאי לבדוק אותו ידנית.
כדי לראות דוגמה להמרת קובץ
xmlל-yamlמוצלחת, אפשר לעבור לכרטיסיות העברה ידנית של קבצים.
העברת הקבצים באופן ידני
כדי להעביר ידנית את קובצי xml לקובצי yaml:
cron.yaml
יוצרים קובץ cron.yaml עם אובייקט cron שמכיל רשימה של אובייקטים, כל אחד עם שדות שתואמים למאפייני התג <cron> בקובץ cron.xml, כמו שמוצג בהמשך.
קובץ cron.yaml שהומר:
cron:
- url: '/recache'
schedule: 'every 2 minutes'
description: 'Repopulate the cache every 2 minutes'
- url: '/weeklyreport'
schedule: 'every monday 08:30'
target: 'version-2'
timezone: 'America/New_York'
description: 'Mail out a weekly report'
קובץ cron.xml מקורי:
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/recache</url>
<description>Repopulate the cache every 2 minutes</description>
<schedule>every 2 minutes</schedule>
</cron>
<cron>
<url>/weeklyreport</url>
<description>Mail out a weekly report</description>
<schedule>every monday 08:30</schedule>
<timezone>America/New_York</timezone>
<target>version-2</target>
</cron>
</cronentries>
מידע נוסף מופיע במאמרי העזרה בנושא cron.yaml.
dispatch.yaml
יוצרים קובץ dispatch.yaml עם אובייקט dispatch שמכיל רשימה של אובייקטים, שלכל אחד מהם יש שדות שתואמים למאפיינים של תג <dispatch> בקובץ dispatch.xml, כמו שמוצג בהמשך.
קובץ dispatch.yaml שהומר:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
קובץ dispatch.xml מקורי
<?xml version="1.0" encoding="UTF-8"?>
<dispatch-entries>
<dispatch>
<url>*/favicon.ico</url>
<module>default</module>
</dispatch>
<dispatch>
<url>simple-sample.uc.r.appspot.com/</url>
<module>default</module>
</dispatch>
<dispatch>
<url>*/mobile/*</url>
<module>mobile-frontend</module>
</dispatch>
</dispatch-entries>
מידע נוסף מופיע במאמרי העזרה בנושא dispatch.yaml.
index.yaml
יוצרים קובץ index.yaml עם אובייקט indexes שמכיל רשימה של אובייקטים, שלכל אחד מהם יש שדות שתואמים לכל אחד ממאפייני התג <datastore-index> בקובץ datastore-indexes.xml, כמו שמוצג בהמשך.
קובץ index.yaml שהומר:
indexes:
- ancestor: false
kind: Employee
properties:
- direction: asc
name: lastName
- direction: desc
name: hireDate
- ancestor: false
kind: Project
properties:
- direction: asc
name: dueDate
- direction: desc
name: cost
קובץ datastore-index.xml מקורי:
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes
autoGenerate="true">
<datastore-index kind="Employee" ancestor="false">
<property name="lastName" direction="asc" />
<property name="hireDate" direction="desc" />
</datastore-index>
<datastore-index kind="Project" ancestor="false">
<property name="dueDate" direction="asc" />
<property name="cost" direction="desc" />
</datastore-index>
</datastore-indexes>
מידע נוסף מופיע במאמרי העזרה בנושא index.yaml.
queue.yaml
יוצרים קובץ queue.yaml עם אובייקט queue שמכיל רשימה של אובייקטים, שלכל אחד מהם יש שדות שתואמים למאפיינים של תג <queue> בקובץ queue.xml, כמו שמוצג בהמשך.
קובץ queue.yaml שהומר:
queue:
- name: fooqueue
mode: push
rate: 1/s
retry_parameters:
task_retry_limit: 7
task_age_limit: 2d
- name: barqueue
mode: push
rate: 1/s
retry_parameters:
min_backoff_seconds: 10
max_backoff_seconds: 200
max_doublings: 0
קובץ queue.xml מקורי:
<queue-entries>
<queue>
<name>fooqueue</name>
<rate>1/s</rate>
<retry-parameters>
<task-retry-limit>7</task-retry-limit>
<task-age-limit>2d</task-age-limit>
</retry-parameters>
</queue>
<queue>
<name>barqueue</name>
<rate>1/s</rate>
<retry-parameters>
<min-backoff-seconds>10</min-backoff-seconds>
<max-backoff-seconds>200</max-backoff-seconds>
<max-doublings>0</max-doublings>
</retry-parameters>
</queue>
<queue-entries>