יצירה ופריסה של פונקציית HTTP ב-Cloud Run באמצעות Java (דור ראשון)

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

  • פונקציית HTTP, שמפעילים אותה מבקשות HTTP רגילות.
  • פונקציה מבוססת-אירועים, שמשמשת לטיפול באירועים מהתשתית של Cloud, כמו הודעות בנושא Pub/Sub או שינויים בקטגוריה של Cloud Storage.

במסמך הזה מוסבר איך ליצור פונקציית HTTP פשוטה ולבנות אותה באמצעות Maven או Gradle.

לפני שמתחילים

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

  3. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  4. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  5. יוצרים או בוחרים Google Cloud פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (יצירת פרויקטים) (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Google Cloud פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Google Cloud שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Google Cloud

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Google Cloud .

  6. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  7. מפעילים את Cloud Functions API ואת Cloud Build API:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable cloudfunctions cloudbuild.googleapis.com
  8. התקינו את ה-CLI של Google Cloud.

  9. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  10. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  11. יוצרים או בוחרים Google Cloud פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (יצירת פרויקטים) (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Google Cloud פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Google Cloud שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Google Cloud

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Google Cloud .

  12. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  13. מפעילים את Cloud Functions API ואת Cloud Build API:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable cloudfunctions cloudbuild.googleapis.com
  14. מכינים את סביבת הפיתוח.

    מעבר למדריך ההגדרה של Java

יצירת פונקציה

בקטע הזה נסביר איך ליצור פונקציה.

Maven

  1. יוצרים ספרייה במערכת המקומית לקוד הפונקציה:

    Linux או Mac OS X:

     mkdir ~/helloworld
     cd ~/helloworld
    

    Windows:

     mkdir %HOMEPATH%\helloworld
     cd %HOMEPATH%\helloworld
    
  2. יוצרים את מבנה הפרויקט שיכיל את ספריית קובצי המקור ואת קובץ המקור.

    mkdir -p src/main/java/functions
    touch src/main/java/functions/HelloWorld.java
    
  3. מוסיפים את התוכן הבא לקובץ HelloWorld.java:

    
    package functions;
    
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import java.io.BufferedWriter;
    import java.io.IOException;
    
    public class HelloWorld implements HttpFunction {
      // Simple function to return "Hello World"
      @Override
      public void service(HttpRequest request, HttpResponse response)
          throws IOException {
        BufferedWriter writer = response.getWriter();
        writer.write("Hello World!");
      }
    }

    הפונקציה בדוגמה הזו מחזירה את הברכה 'Hello World!‎'.

Gradle

  1. יוצרים ספרייה במערכת המקומית לקוד הפונקציה:

    Linux או Mac OS X:

     mkdir ~/helloworld-gradle
     cd ~/helloworld-gradle
    

    Windows:

     mkdir %HOMEPATH%\helloworld-gradle
     cd %HOMEPATH%\helloworld-gradle
    
  2. יוצרים את מבנה הפרויקט שיכיל את ספריית קובצי המקור ואת קובץ המקור.

     mkdir -p src/main/java/functions
     touch src/main/java/functions/HelloWorld.java
    
  3. מוסיפים את התוכן הבא לקובץ HelloWorld.java:

    
    package functions;
    
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import java.io.BufferedWriter;
    import java.io.IOException;
    
    public class HelloWorld implements HttpFunction {
      // Simple function to return "Hello World"
      @Override
      public void service(HttpRequest request, HttpResponse response)
          throws IOException {
        BufferedWriter writer = response.getWriter();
        writer.write("Hello World!");
      }
    }

    הפונקציה בדוגמה הזו מחזירה את הברכה 'Hello World!‎'.

ציון יחסי תלות

השלב הבא הוא הגדרת יחסי תלות:

Maven

עוברים לספרייה helloworld שיצרתם למעלה ויוצרים קובץ pom.xml:

 cd ~/helloworld
 touch pom.xml

כדי לנהל יחסי תלות באמצעות Maven, מציינים את יחסי התלות בקטע <dependencies> בקובץ pom.xml של הפרויקט. לצורך התרגיל הזה, מעתיקים את התוכן הבא לקובץ pom.xml.

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-hello-world</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
  </properties>

  <dependencies>
    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.HelloWorld</functionTarget>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

דוגמה מלאה שמבוססת על Maven זמינה במאמר helloworld.

Gradle

עוברים לספרייה helloworld-gradle שיצרתם למעלה, ויוצרים קובץ build.gradle:

 cd ~/helloworld-gradle
 touch build.gradle

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

apply plugin: 'java'

repositories {
  jcenter()
  mavenCentral()
}
configurations {
    invoker
}

dependencies {
  // Every function needs this dependency to get the Functions Framework API.
  compileOnly 'com.google.cloud.functions:functions-framework-api:1.1.0'

  // To run function locally using Functions Framework's local invoker
  invoker 'com.google.cloud.functions.invoker:java-function-invoker:1.3.1'

  // These dependencies are only used by the tests.
  testImplementation 'com.google.cloud.functions:functions-framework-api:1.1.0'
  testImplementation 'junit:junit:4.13.2'
  testImplementation 'com.google.truth:truth:1.4.0'
  testImplementation 'org.mockito:mockito-core:5.10.0'

}

// Register a "runFunction" task to run the function locally
tasks.register("runFunction", JavaExec) {
  main = 'com.google.cloud.functions.invoker.runner.Invoker'
  classpath(configurations.invoker)
  inputs.files(configurations.runtimeClasspath, sourceSets.main.output)
  args(
    '--target', project.findProperty('run.functionTarget') ?: '',
    '--port', project.findProperty('run.port') ?: 8080
  )
  doFirst {
    args('--classpath', files(configurations.runtimeClasspath, sourceSets.main.output).asPath)
  }
}

דוגמה מלאה שמבוססת על Gradle זמינה במאמר helloworld-gradle.

פיתוח ובדיקה באופן מקומי

לפני שמפיצים את הפונקציה, אפשר ליצור ולבדוק אותה באופן מקומי:

Maven

מריצים את הפקודה הבאה כדי לוודא שהפונקציה נוצרת:

mvn compile

אפשרות נוספת היא להשתמש בפקודה mvn package כדי לקמפל את קוד ה-Java, להריץ בדיקות ולארוז את הקוד בקובץ JAR בספריית היעד. מידע נוסף על מחזור החיים של Maven build

כדי לבדוק את הפונקציה, מריצים את הפקודה הבאה:

mvn function:run

Gradle

מריצים את הפקודה הבאה כדי לוודא שהפונקציה נוצרת:

gradle build

כדי לבדוק את הפונקציה, מריצים את הפקודה הבאה:

gradle runFunction -Prun.functionTarget=functions.HelloWorld

אם הבדיקה מסתיימת בהצלחה, מוצגת כתובת ה-URL שאפשר להיכנס אליה בדפדפן האינטרנט כדי לראות את הפונקציה בפעולה: http://localhost:8080/. אמורה להופיע ההודעה Hello World!.

לחלופין, אפשר לשלוח בקשות לפונקציה הזו באמצעות curl מחלון טרמינל אחר:

curl localhost:8080
# Output: Hello World!

פריסת הפונקציה

Maven

כדי לפרוס את הפונקציה עם טריגר HTTP, מריצים את הפקודה הבאה בספרייה helloworld:

gcloud functions deploy my-first-function --no-gen2 --entry-point functions.HelloWorld --runtime java17 --trigger-http --memory 512MB --allow-unauthenticated
כאשר my-first-function הוא השם הרשום שבאמצעותו הפונקציה תזוהה במסוף Google Cloud , ו---entry-point מציין את שם המחלקה המוגדר במלואו (FQN) של הפונקציה.

Gradle

כדי לפרוס את הפונקציה עם טריגר HTTP, מריצים את הפקודה הבאה בספרייה helloworld-gradle:

gcloud functions deploy my-first-function --no-gen2 --entry-point functions.HelloWorld --runtime java17 --trigger-http --memory 512MB --allow-unauthenticated
כאשר my-first-function הוא השם הרשום שבאמצעותו הפונקציה תזוהה במסוף Google Cloud , ו---entry-point מציין את שם המחלקה המוגדר במלואו (FQN) של הפונקציה.

בדיקת הפונקציה שנפרסה

  1. אחרי שהפונקציה מסיימת את הפריסה, רושמים את המאפיין httpsTrigger.url או מאתרים אותו באמצעות הפקודה הבאה:

    gcloud functions describe my-first-function
    הוא אמור להיראות כך:

    https://GCP_REGION-PROJECT_ID.cloudfunctions.net/my-first-function
  2. נכנסים לכתובת ה-URL הזו בדפדפן. אמורה להופיע ההודעה Hello World!.

צפייה ביומנים

אפשר לראות את היומנים של פונקציות Cloud Run באמצעות Google Cloud CLI ובממשק המשתמש של Cloud Logging.

שימוש בכלי שורת הפקודה

כדי להציג את היומנים של הפונקציה באמצעות ה-CLI של gcloud, משתמשים בפקודה logs read ואחריה בשם הפונקציה:

gcloud functions logs read my-first-function

הפלט אמור להיראות כך:

LEVEL  NAME               EXECUTION_ID  TIME_UTC                 LOG
D      my-first-function  k2bqgroszo4u  2020-07-24 18:18:01.791  Function execution started
D      my-first-function  k2bqgroszo4u  2020-07-24 18:18:01.958  Function execution took 168 ms, finished with status code: 200
...

שימוש בלוח הבקרה של הרישום ביומן

אפשר גם לצפות ביומנים של פונקציות Cloud Run ממסוףGoogle Cloud .