אופטימיזציה של אפליקציות Java ל-Cloud Run

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

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

הרבה מהשיטות המומלצות והאופטימיזציות באפליקציות רגילות מבוססות-אינטרנט של Java מתמקדות ב:

  • טיפול בבקשות מקבילות (גם מבוססות-thread וגם I/O לא חוסם)
  • הפחתת זמן האחזור של התגובה באמצעות איגום חיבורים (connection pooling) ועיבוד באצווה של פונקציות לא קריטיות, למשל שליחת עקבות ומדדים למשימות ברקע.

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

שימוש בהגברת מהירות המעבד (CPU) בזמן ההפעלה כדי להפחית את זמן האחזור של ההפעלה

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

המדדים של Google הראו שאפליקציות Java נהנות משימוש בהגברת מהירות המעבד בהפעלה, שיכולה לקצר את זמני ההפעלה ב-50% לכל היותר.

אופטימיזציה של קובץ אימג' של קונטיינר של אפליקציית Java

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

  • מזעור של קובץ אימג' של קונטיינר
  • הימנעות משימוש בקובצי JAR של ארכיון ספריות מקוננות
  • שימוש ב-Jib

מזעור קובץ האימג' של הקונטיינר

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

  • קוד מקור
  • פריטי מידע שנוצרו בתהליך פיתוח (Artifact) של Maven
  • כלי בנייה
  • ספריות Git
  • קובצי הפעלה או כלי עזר שלא בשימוש

אם אתם יוצרים את הקוד מתוך קובץ Docker, השתמשו ב-Docker multi-stage build כדי שקובץ אימג' של קונטיינר הסופי יכלול רק את JRE ואת קובץ ה-JAR של האפליקציה עצמה.

כדאי להימנע מקובצי JAR של ספריות מקוננות

חלק מהמסגרות הפופולריות, כמו Spring Boot, יוצרות קובץ ארכיון של אפליקציה (JAR) שמכיל קובצי JAR נוספים של ספריות (JARs מוטבעים). צריך לפתוח את הקבצים האלה (לבטל את הדחיסה שלהם) בזמן ההפעלה, וזה עלול להשפיע לרעה על מהירות ההפעלה ב-Cloud Run. לכן, כשזה אפשרי, כדאי ליצור קובץ JAR דק עם ספריות חיצוניות. אפשר לבצע את הפעולה הזו באופן אוטומטי באמצעות Jib כדי להכניס את האפליקציה שלכם לקונטיינר.

שימוש ב-Jib

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

אופטימיזציות של JVM לאפליקציות Java ב-Cloud Run

אופטימיזציה של ה-JVM בשביל שירות Cloud Run יכולה לשפר את הביצועים ואת השימוש בזיכרון.

שימוש בגרסאות JVM שמתאימות לקונטיינרים

במכונות וירטואליות ובמכונות, כדי להקצות מעבד (CPU) וזיכרון, ה-JVM מבין את המעבד והזיכרון שהוא יכול להשתמש בהם ממיקומים ידועים, לדוגמה, ב-Linux,‏ /proc/cpuinfo ו-/proc/meminfo. עם זאת, כשמריצים את התהליך בקונטיינר, מגבלות המעבד והזיכרון מאוחסנות ב-/proc/cgroups/.... גרסאות ישנות יותר של JDK ממשיכות לחפש ב-/proc במקום ב-/proc/cgroups, מה שיכול לגרום לשימוש רב יותר במעבד (CPU) ובשימוש בזיכרון ממה שהוקצה. המצב הזה יכול לגרום ל:

  • מספר מוגזם של שרשורים כי גודל מאגר השרשורים מוגדר על ידי Runtime.availableProcessors()
  • גודל ערימה מקסימלי שחורג ממגבלת הזיכרון של המאגר. מכונת ה-JVM משתמשת בזיכרון באופן אגרסיבי לפני שהיא מבצעת איסוף אשפה. במצב כזה, קל מאוד לחרוג ממגבלת הזיכרון של הקונטיינר ולגרום להפסקת הפעולה שלו בגלל חוסר זיכרון (OOM).

לכן, צריך להשתמש בגרסת JVM שמודעת לקונטיינר. גרסאות OpenJDK גדולות או שוות לגרסה 8u192 מודעות לקונטיינר כברירת מחדל.

איך מבינים את השימוש בזיכרון של JVM

השימוש בזיכרון של JVM מורכב משימוש בזיכרון מקורי ומשימוש בערימה. זיכרון העבודה של האפליקציה נמצא בדרך כלל ב-heap. הגודל של ה-heap מוגבל על ידי ההגדרה Max Heap. במופע של Cloud Run עם זיכרון RAM של 256MB, אי אפשר להקצות את כל הזיכרון הזה ל-Max Heap, כי גם JVM ומערכת ההפעלה דורשים זיכרון מקומי, למשל, מחסנית של שרשור, מטמוני קוד, ידיות קבצים, מאגרי נתונים זמניים וכו'. אם האפליקציה שלכם נסגרת בגלל חוסר זיכרון (OOMKilled) ואתם רוצים לדעת מה השימוש בזיכרון של JVM (זיכרון מקומי + Heap), אתם יכולים להפעיל את האפשרות Native Memory Tracking (מעקב אחרי זיכרון מקומי) כדי לראות את השימוש בזיכרון אחרי שהאפליקציה נסגרת בהצלחה. אם האפליקציה שלכם נסגרת בגלל חריגה של זיכרון (OOM), היא לא תוכל להדפיס את המידע. במקרה כזה, צריך להריץ את האפליקציה עם יותר זיכרון כדי שהיא תוכל ליצור את הפלט בהצלחה.

אי אפשר להפעיל את מעקב הזיכרון המקורי באמצעות משתנה הסביבה JAVA_TOOL_OPTIONS. צריך להוסיף את ארגומנט ההפעלה של שורת הפקודה של Java לנקודת הכניסה של קובץ אימג' של קונטיינר, כדי שהאפליקציה תופעל עם הארגומנטים האלה:

java -XX:NativeMemoryTracking=summary \
  -XX:+UnlockDiagnosticVMOptions \
  -XX:+PrintNMTStatistics \
  ...

כדאי להשתמש במחשבון זיכרון Java בקוד פתוח כדי להעריך את צורכי הזיכרון.

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

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

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

בשירות Cloud Run, מגדירים את משתנה הסביבה:

JAVA_TOOL_OPTIONS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"

שימוש בשיתוף נתונים של מחלקות אפליקציות

כדי לצמצם עוד יותר את זמן ה-JIT ואת השימוש בזיכרון, אפשר להשתמש בשיתוף נתוני מחלקות של אפליקציות (AppCDS) כדי לשתף את מחלקות ה-Java שעברו הידור מראש כארכיון. אפשר לעשות שימוש חוזר בארכיון AppCDS כשמפעילים מופע נוסף של אותה אפליקציית Java. מכונת ה-JVM יכולה לעשות שימוש חוזר בנתונים שחושבו מראש מהארכיון, וכך לקצר את זמן ההפעלה.

השיקולים הבאים רלוונטיים לשימוש ב-AppCDS:

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

דוגמה לשימוש ב-Spring Boot בקובץ JAR מוצלל

אפליקציות Spring Boot משתמשות ב-uber JAR מוטמע כברירת מחדל, שלא יפעל ב-AppCDS. לכן, אם אתם משתמשים ב-AppCDS, אתם צריכים ליצור JAR מוצלל. לדוגמה, באמצעות Maven ותוסף Maven Shade:

<build>
  <finalName>helloworld</finalName>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <configuration>
        <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
        <createDependencyReducedPom>true</createDependencyReducedPom>
        <filters>
          <filter>
            <artifact>*:*</artifact>
            <excludes>
              <exclude>META-INF/*.SF</exclude>
              <exclude>META-INF/*.DSA</exclude>
              <exclude>META-INF/*.RSA</exclude>
            </excludes>
          </filter>
        </filters>
      </configuration>
      <executions>
        <execution>
          <phase>package</phase>
          <goals><goal>shade</goal></goals>
          <configuration>
            <transformers>
              <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.handlers</resource>
              </transformer>
              <transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                <resource>META-INF/spring.factories</resource>
              </transformer>
              <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.schemas</resource>
              </transformer>
              <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
              <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>${mainClass}</mainClass>
              </transformer>
            </transformers>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

אם קובץ ה-JAR המוצלל מכיל את כל התלויות, אפשר ליצור ארכיון פשוט במהלך בניית הקונטיינר באמצעות Dockerfile:

# Use Docker's multi-stage build
FROM eclipse-temurin:11-jre as APPCDS

COPY target/helloworld.jar /helloworld.jar

# Run the application, but with a custom trigger that exits immediately.
# In this particular example, the application looks for the '--appcds' flag.
# You can implement a similar flag in your own application.
RUN java -XX:DumpLoadedClassList=classes.lst -jar helloworld.jar --appcds=true

# From the captured list of classes (based on execution coverage),
# generate the AppCDS archive file.
RUN java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=appcds.jsa --class-path helloworld.jar

FROM eclipse-temurin:11-jre

# Copy both the JAR file and the AppCDS archive file to the runtime container.
COPY --from=APPCDS /helloworld.jar /helloworld.jar
COPY --from=APPCDS /appcds.jsa /appcds.jsa

# Enable Application Class-Data sharing
ENTRYPOINT java -Xshare:on -XX:SharedArchiveFile=appcds.jsa -jar helloworld.jar

הקטנת גודל מחסנית השרשור

רוב אפליקציות האינטרנט ב-Java מבוססות על thread לכל חיבור. כל שרשור Java צורך זיכרון מקומי (לא ב-heap). האזור הזה נקרא מחסנית השרשור, וגודל ברירת המחדל שלו הוא 1MB לכל שרשור. אם האפליקציה מטפלת ב-80 בקשות בו-זמניות, יכול להיות שיש לה לפחות 80 שרשורים, כלומר 80MB של שטח מחסנית שרשורים בשימוש. הזיכרון הזה הוא בנוסף לגודל הערימה. יכול להיות שערך ברירת המחדל גדול מהנדרש. אפשר להקטין את גודל מחסנית השרשור.

אם תצמצמו יותר מדי, תראו את java.lang.StackOverflowError. אפשר ליצור פרופיל של האפליקציה ולמצוא את גודל מחסנית השרשור האופטימלי להגדרה.

בשירות Cloud Run, מגדירים את משתנה הסביבה:

JAVA_TOOL_OPTIONS="-Xss256k"

הפחתת מספר ה-threads לשיפור הביצועים של אפליקציות Java

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

הפחתת מספר השרשורים

כל שרשור Java עשוי להגדיל את השימוש בזיכרון בגלל Thread Stack. ב-Cloud Run אפשר להשתמש בעד 1,000 בקשות בו-זמנית. במודל של שרשור לכל חיבור, צריך לכל היותר 1,000 שרשורים כדי לטפל בכל הבקשות בו-זמנית. ברוב שרתי האינטרנט ומסגרות העבודה אפשר להגדיר את המספר המקסימלי של השרשורים והחיבורים. לדוגמה, ב-Spring Boot, אפשר להגביל את מספר החיבורים המקסימלי בקובץ applications.properties:

server.tomcat.max-threads=80

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

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

לרוב, למסגרות תגובתיות כמו Spring Boot עם Webflux, ‏ Micronaut ו-Quarkus יש זמני הפעלה מהירים יותר.

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

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

אם אתם משתמשים בפעילויות ברקע, אתם צריכים להגדיר חיוב לפי מופע

פעילות ברקע היא כל מה שקורה אחרי שתגובת ה-HTTP נמסרת. עומסי עבודה מסורתיים שיש להם משימות ברקע דורשים התייחסות מיוחדת כשמריצים אותם ב-Cloud Run.

הגדרת חיוב לפי מופע

אם רוצים לתמוך בפעילויות ברקע בשירות Cloud Run, צריך להגדיר את שירות Cloud Run לחיוב לפי מופע כדי להריץ פעילויות ברקע מחוץ לבקשות ועדיין לקבל גישה למעבד.

אם אתם משתמשים בחיוב לפי בקשה, מומלץ להימנע מפעילויות ברקע

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

יש כמה דפוסים מוכרים שפועלים ברקע וחשוב לשים לב אליהם אם בוחרים בחיוב לפי בקשה:

  • מאגרי חיבורים של JDBC – ניקויים ובדיקות חיבורים מתרחשים בדרך כלל ברקע
  • שולחי מעקב מבוזר – בדרך כלל, מעקבים מבוזרים נשלחים בקבוצות באופן תקופתי או כשהמאגר מלא ברקע.
  • שולחי מדדים – בדרך כלל המדדים נשלחים בקבוצות באופן תקופתי ברקע.
  • ב-Spring Boot, כל השיטות שמסומנות בהערה @Async
  • טיימרים – כל הטריגרים שמבוססים על טיימר (למשל, יכול להיות שהפעולה לא תתבצע אם מוגדר חיוב לפי בקשה (למשל, ScheduledThreadPoolExecutor, ‏ Quartz או @Scheduled Spring annotation).
  • מקבלים של הודעות – לדוגמה, לקוחות של Pub/Sub streaming pull, לקוחות של JMS או לקוחות של Kafka, בדרך כלל פועלים בשרשורים ברקע בלי צורך בבקשות. הן לא יפעלו אם לא יהיו בקשות באפליקציה. לא מומלץ לקבל הודעות בדרך הזו ב-Cloud Run.

אופטימיזציה של אפליקציות

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

הפחתת משימות ההפעלה

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

‫Cloud Run שולח בקשה ממשתמש אמיתי כדי להפעיל מופע של הפעלה קרה. יכול להיות שמשתמשים שהוקצתה להם בקשה במופע שהופעל לאחרונה יחוו עיכובים ארוכים.

עבור אפליקציות עם זמני הפעלה ארוכים, כדאי להשתמש בבקשה לבדיקת תקינות (probe) של הפעלה. בדיקת ההפעלה מוודאת ש-Cloud Run שולח בקשות משתמש למופע רק אחרי שהוא מאותחל באופן מלא ועובר את בדיקת התקינות של ההפעלה. מידע נוסף זמין במאמר הגדרת בדיקות תקינות של קונטיינרים לשירותים.

שימוש במאגר חיבורים

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

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

אם משתמשים ב-Spring Boot

אם אתם משתמשים ב-Spring Boot, כדאי לשקול את האופטימיזציות הבאות

שימוש ב-Spring Boot בגרסה 2.2 ומעלה

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

שימוש באתחול מדורג

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

אפשר להפעיל את האתחול המדורג בapplication.properties:

spring.main.lazy-initialization=true

או באמצעות משתנה סביבה:

SPRING_MAIN_LAZY_INITIALIZATIION=true

עם זאת, אם אתם משתמשים ב-min-instances, אתחול עצל לא יעזור, כי האתחול אמור להתרחש כש-min-instance מתחיל.

איך להימנע מסריקת כיתות

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

שימוש בכלים למפתחים של Spring Boot שלא בסביבת ייצור

אם אתם משתמשים בכלי הפיתוח Spring Boot במהלך הפיתוח, הקפידו שלא לארוז אותו בתמונת קונטיינר הייצור. זה יכול לקרות אם יצרתם את אפליקציית Spring Boot בלי התוספים של Spring Boot build (לדוגמה, באמצעות התוסף Shade או באמצעות Jib ליצירת קונטיינר).

במקרים כאלה, צריך לוודא שכלי ה-build מחריג במפורש את כלי הפיתוח של Spring Boot. או משביתים את הכלי למפתחים של Spring Boot באופן מפורש).

המאמרים הבאים

טיפים נוספים זמינים במאמר