Java-Bereitstellungsoptionen

Sie haben zwei Möglichkeiten, eine Java-Funktion bereitzustellen:

Über Quelle bereitstellen

Der Quellcode Ihrer Funktion muss am gewohnten Speicherort für Maven-Projekte abgelegt sein (src/main/java). Die Beispielfunktionen in diesem Dokument befinden sich direkt in src/main/java, ohne Paketdeklaration in der Quelldatei .java. Für komplexeren Code werden Sie vermutlich ein Paket verwenden. Wenn dieses Paket com.example ist, würde Ihre Hierarchie so aussehen:

myfunction/
├─ pom.xml
├─ src
    ├─main
        ├─ java
            ├─ com
                ├─ example
                    ├─ MyFunction.java

Verwenden Sie den folgenden Befehl, um eine HTTP-Funktion bereitzustellen:

gcloud functions deploy $name --trigger-http \
    --entry-point $function_class --runtime java17

Dabei gilt:

  • $name ist ein beliebiger, beschreibender Name, der nach der Bereitstellung der Name der Funktion ist. $name darf nur Buchstaben, Zahlen, Unterstriche und Bindestriche enthalten.
  • $function_class ist der voll qualifizierte Name der Klasse, z. B. com.example.MyFunction oder einfach MyFunction, wenn Sie kein Paket verwenden.

Verwenden Sie den folgenden Befehl, um eine Hintergrundfunktion bereitzustellen:

gcloud functions deploy $name --entry-point $function_class \
    --trigger-resource $resource_name \
    --trigger-event $event_name \
    --runtime java17

Dabei gilt:

  • $name ist ein beliebiger, beschreibender Name, der nach der Bereitstellung der Name der Funktion ist.
  • $function_class ist der voll qualifizierte Name der Klasse, z. B. com.example.MyFunction oder einfach MyFunction, wenn Sie kein Paket verwenden.
  • $resource_name und $event_name richten sich jeweils nach den Ereignissen, die die Hintergrundfunktion auslösen. Unterstützte Ressourcen und Ereignisse sind beispielsweise Google Cloud Pub/Sub und Google Cloud Storage.

Wenn Sie eine Funktion aus der Quelle bereitstellen, lädt die Google Cloud CLI das Quellverzeichnis (und dessen gesamten Inhalt) für den Build in Google Cloud hoch. Damit keine unnötigen Dateien gesendet werden, können Sie die Datei .gcloudignore verwenden. Bearbeiten Sie die Datei .gcloudignore, um allgemeine Verzeichnisse wie .git und target/ zu ignorieren. Eine .gcloudignore-Datei könnte beispielsweise Folgendes enthalten:

.git
target
build
.idea

Über eine JAR-Datei bereitstellen

Sie können eine vordefinierte JAR-Datei bereitstellen, die die Funktion enthält. Dies ist insbesondere beim Bereitstellen einer Funktion hilfreich, die Abhängigkeiten aus einem privaten Artefakt-Repository verwendet, auf das beim Erstellen aus der Quelle nicht von der Build-Pipeline von Google Cloud zugegriffen werden kann. Die JAR-Datei kann eine Uber-JAR-Datei sein, die die Funktionsklasse und alle Abhängigkeitsklassen enthält, oder eine schlanke JAR-Datei mit Class-Path-Einträgen für Abhängigkeits-JARs in der Datei META-INF/MANIFEST.MF.

Uber-JAR-Datei erstellen und bereitstellen

Eine Uber-JAR-Datei ist eine JAR-Datei, die die Funktionsklassen und alle zugehörigen Abhängigkeiten enthält. Sie können eine Uber-JAR-Datei mit Maven und Gradle erstellen. Wenn Sie eine Uber-JAR-Datei bereitstellen möchten, muss diese die einzige JAR-Datei in ihrem eigenen Verzeichnis sein. Beispiel:

my-function-deployment/
 ├─ my-function-with-all-dependencies.jar

Sie können entweder die Datei in diese Verzeichnisstruktur kopieren oder mit Maven- und Gradle-Plug-ins das korrekte Bereitstellungsverzeichnis generieren.

Maven

Verwenden Sie das Shade-Plug-in von Maven, um eine Uber-JAR-Datei zu erstellen. Konfigurieren Sie Ihre pom.xml mit dem Shade-Plug-in:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals><goal>shade</goal></goals>
            <configuration>
              <outputFile>${project.build.directory}/deployment/${build.finalName}.jar</outputFile>
              <transformers>
                <!-- This may be needed if you need to shade a signed JAR -->
                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                  <resource>.SF</resource>
                  <resource>.DSA</resource>
                  <resource>.RSA</resource>
                </transformer>
                <!-- This is needed if you have dependencies that use Service Loader. Most Google Cloud client libraries does. -->
                <transformer implementation=
       "org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Erstellen Sie die Uber-JAR-Datei:

mvn package

Führen Sie dann die Bereitstellung mit dem folgenden Befehl aus:

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java17 \
    --trigger-http \
    --source=target/deployment

Gradle

Verwenden Sie das Shadow-Plug-in für Gradle. Richten Sie das Plug-in in der Datei build.gradle ein:

buildscript {
   repositories {
       jcenter()
   }
   dependencies {
       ...
       classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0"
   }
}

plugins {
   id 'java'
   ...
}
sourceCompatibility = '17.0'
targetCompatibility = '17.0'
apply plugin: 'com.github.johnrengelman.shadow'

shadowJar {
   mergeServiceFiles()
}
...

Jetzt können Sie Gradle mit dem Befehl shadowJar ausführen:

gradle shadowJar

Führen Sie dann die Bereitstellung mit dem folgenden Befehl aus:

gcloud functions deploy jar-example \
   --entry-point=Example \
   --runtime=java17 \
   --trigger-http \
   --source=build/libs

Schlanke JAR-Datei mit externen Abhängigkeiten erstellen und bereitstellen

Sie können anstelle einer Uber-JAR-Datei auch eine schlanke JAR-Datei erstellen und bereitstellen. Eine schlanke JAR-Datei ist eine JAR-Datei, die nur die Funktionsklassen enthält, ohne dass die Abhängigkeiten in derselben JAR-Datei eingebettet sind. Da die Abhängigkeiten weiterhin für die Bereitstellung benötigt werden, müssen folgende Voraussetzungen geschaffen werden:

  • Die Abhängigkeiten müssen sich in einem Unterverzeichnis relativ zur JAR-Datei befinden, die bereitgestellt werden soll.
  • Die JAR-Datei muss eine META-INF/MANIFEST.MF-Datei mit einem Class-Path-Attribut enthalten, dessen Wert eine Liste der Pfade zu den erforderlichen Abhängigkeiten ist.

Ihre JAR-Datei „my-function.jar“ enthält beispielsweise eine META-INF/MANIFEST.MF-Datei mit zwei Abhängigkeiten im Verzeichnis libs/ (eine durch Leerzeichen getrennte Liste relativer Pfade):

Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar

Ihr Bereitstellungsverzeichnis sollte dann die JAR-Hauptdatei mit der Funktion sowie ein Unterverzeichnis mit den beiden Abhängigkeiten enthalten, auf die die Funktion angewiesen ist:

function-deployment/
├─ my-function.jar
├─ libs
       ├─ dep1.jar
       ├─ dep2.jar

Sie können eine schlanke JAR-Datei mit Maven und Gradle erstellen:

Maven

Verwenden Sie das JAR-Plug-in von Maven, um MANIFEST.MF automatisch mit den Pfaden zu den Abhängigkeiten zu konfigurieren, und kopieren Sie dann die Abhängigkeiten mit dem Dependency-Plug-in von Maven.

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>libs/</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <overWriteReleases>false</overWriteReleases>
              <includeScope>runtime</includeScope>
              <outputDirectory>${project.build.directory}/libs</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>package</phase>
            <goals><goal>copy-resources</goal></goals>
            <configuration>
              <outputDirectory>${project.build.directory}/deployment</outputDirectory>
              <resources>
                <resource>
                  <directory>${project.build.directory}</directory>
                  <includes>
                    <include>${build.finalName}.jar</include>
                    <include>libs/**</include>
                  </includes>
                  <filtering>false</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Erstellen Sie die schlanke JAR-Datei:

mvn package

Führen Sie dann die Bereitstellung mit dem folgenden Befehl aus:

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java17 \
    --trigger-http \
    --source=target/deployment

Gradle

Aktualisieren Sie die Projektdatei build.gradle mit einer neuen Aufgabe, um die Abhängigkeiten abzurufen:

dependencies {
   // API available at compilation only, but provided at runtime
   compileOnly 'com.google.cloud.functions:functions-framework-api:1.0.1'
   // dependencies needed by the function
   // ...
}

jar {
 manifest {
   attributes(
     "Class-Path": provider {
         configurations.runtimeClasspath
           .collect { "libs/${it.name}" }.join(' ')
     }
   )
 }
}

task prepareDeployment(type: Copy) {
 into("${buildDir}/deployment")
 into('.') {
   from jar
 }
 into('libs') {
   from configurations.runtimeClasspath
 }
}