Opzioni di deployment Java

Per eseguire il deployment di una funzione Java, hai due opzioni:

Esegui il deployment dall'origine

Il codice sorgente della funzione deve trovarsi nella posizione consueta per i progetti Maven (src/main/java). Le funzioni di esempio in questo documento si trovano direttamente in src/main/java, senza dichiarazione del pacchetto nel file di origine .java. Per il codice non banale, probabilmente introdurrai un pacchetto. Se il pacchetto è com.example, la gerarchia sarà la seguente:

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

Utilizza il seguente comando per eseguire il deployment di una funzione HTTP:

gcloud functions deploy $name \
    --trigger-http \
    --gen2 \
    --region=REGION \
    --entry-point $function_class \
    --runtime java21 

Dove:

  • $name è un nome descrittivo arbitrario che diventerà il nome della funzione al termine del deployment. $name può contenere solo lettere, numeri, trattini bassi e trattini.
  • $function_class è il nome completo della classe (ad esempio, com.example.MyFunction o semplicemente MyFunction se non utilizzi un pacchetto).

Utilizza il comando seguente per eseguire il deployment di una funzione basata su eventi:

gcloud functions deploy $name \
    --entry-point $function_class \
    --gen2 \
    --region=REGION \
    --trigger-resource $resource_name \
    --trigger-event $event_name \
    --runtime java21

Dove:

  • $name è un nome descrittivo arbitrario che diventerà il nome della funzione al termine del deployment.
  • $function_class è il nome completo della classe (ad esempio, com.example.MyFunction o semplicemente MyFunction se non utilizzi un pacchetto).
  • $resource_name e $event_name sono specifici per gli eventi che attivano la funzione basata su eventi. Esempi di risorse ed eventi supportati sono Google Cloud Pub/Sub e Google Cloud Storage.

Quando esegui il deployment di una funzione dal codice sorgente, Google Cloud CLI carica la directory di origine (e tutto ciò che contiene) su Google Cloud per la compilazione. Per evitare di inviare file non necessari, puoi utilizzare il .gcloudignore file. Modifica il file .gcloudignore per ignorare le directory comuni come .git e target/. Ad esempio, un .gcloudignore file potrebbe contenere quanto segue:

.git
target
build
.idea

Esegui il deployment da un file JAR

Puoi eseguire il deployment di un file JAR precompilato che contiene la funzione. Questo è utile soprattutto se devi eseguire il deployment di una funzione che utilizza dipendenze da un repository di elementi privati a cui non è possibile accedere dalla pipeline di build di Google Cloud durante la compilazione dal codice sorgente. Il file JAR può essere un file JAR uber che contiene la classe della funzione e tutte le sue classi di dipendenza oppure un file JAR thin che contiene voci Class-Path per i file JAR delle dipendenze nel file META-INF/MANIFEST.MF.

Crea ed esegui il deployment di un JAR Uber

Un file JAR uber è un file JAR che contiene le classi di funzioni e tutte le sue dipendenze. Puoi creare un uber JAR sia con Maven che con Gradle. Per eseguire il deployment di un file JAR Uber, questo deve essere l'unico file JAR nella relativa directory, ad esempio:

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

Puoi copiare il file in questa struttura di directory o utilizzare i plug-in Maven e Gradle per generare la directory di deployment corretta.

Maven

Utilizza il plug-in Maven Shade per creare un uber JAR. Configura pom.xml con il plug-in Shade:

<?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>

Crea il file JAR di Uber:

mvn package

Esegui il deployment con il seguente comando:

gcloud functions deploy jar-example \
    --gen2 \
    --entry-point=Example \
    --runtime=java21 \
    --region=REGION \
    --trigger-http \
    --source=target/deployment

Gradle

Utilizza il plug-in Shadow per Gradle. Configura il plug-in nel build.gradle file:

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()
}
...

Ora puoi eseguire Gradle con il comando shadowJar:

gradle shadowJar

Esegui il deployment con il seguente comando:

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

Crea ed esegui il deployment di un JAR thin con dipendenze esterne

Puoi creare ed eseguire il deployment di un file JAR thin anziché di un uber JAR. Un file JAR thin è un file JAR che contiene solo le classi di funzioni senza le dipendenze incorporate nello stesso file JAR. Poiché le dipendenze sono ancora necessarie per il deployment, devi configurare le impostazioni come segue:

  • Le dipendenze devono trovarsi in una sottodirectory relativa al JAR da eseguire il deployment.
  • Il file JAR deve avere un file META-INF/MANIFEST.MF che includa un attributo Class-Path il cui valore elenca i percorsi delle dipendenze richieste.

Ad esempio, il file JAR my-function.jar contiene un file META-INF/MANIFEST.MF con due dipendenze nella directory libs/ (un elenco di percorsi relativi separati da spazi):

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

La directory di deployment deve contenere il file JAR della funzione principale, nonché una sottodirectory con le due dipendenze da cui dipende la funzione:

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

Puoi creare un JAR thin sia con Maven che con Gradle:

Maven

Utilizza il plug-in JAR di Maven per configurare automaticamente MANIFEST.MF con i percorsi alle dipendenze, quindi utilizza il plug-in Maven Dependency per copiare le dipendenze.

<?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>

Crea il file JAR thin:

mvn package

Esegui il deployment con il seguente comando:

gcloud functions deploy jar-example \
--gen2 \
--region=REGION \
--entry-point=Example \
--runtime=java21 \
--trigger-http \
--source=target/deployment

Gradle

Aggiorna il file del progetto build.gradle per aggiungere una nuova attività per recuperare le dipendenze:

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
 }
}