Opciones de implementación de Java
Tienes dos opciones para desplegar una función de Java:
- De fuente. Para obtener información general sobre este tema, consulta Desplegar una función de Cloud.
- Desde un archivo JAR preempaquetado.
Desplegar desde el código fuente
El código fuente de tu función debe estar en la ubicación habitual de los proyectos de Maven (src/main/java
). Las funciones de ejemplo de este documento se encuentran directamente en src/main/java
, sin ninguna declaración de paquete en el archivo de origen .java
. En el caso de código no trivial, probablemente introducirías un paquete. Si el paquete es com.example
, la jerarquía sería la siguiente:
myfunction/ ├─ pom.xml ├─ src ├─main ├─ java ├─ com ├─ example ├─ MyFunction.java
Usa el siguiente comando para desplegar una función HTTP:
gcloud functions deploy $name --trigger-http --no-gen2 \
--entry-point $function_class --runtime java17
Donde:
$name
es un nombre descriptivo arbitrario que será el nombre de la función una vez implementada.$name
solo puede contener letras, números, guiones bajos y guiones.$function_class
es el nombre completo de tu clase (por ejemplo,com.example.MyFunction
o simplementeMyFunction
si no usas ningún paquete).
Usa el siguiente comando para desplegar una función basada en eventos:
gcloud functions deploy $name --no-gen2 --entry-point $function_class \
--trigger-resource $resource_name \
--trigger-event $event_name \
--runtime java17
Donde:
$name
es un nombre descriptivo arbitrario que será el nombre de la función una vez implementada.$function_class
es el nombre completo de tu clase (por ejemplo,com.example.MyFunction
o simplementeMyFunction
si no usas ningún paquete).$resource_name
y$event_name
son específicos de los eventos que activan tu función. Algunos ejemplos de recursos y eventos admitidos son Google Cloud Pub/Sub y Google Cloud Storage.
Cuando se despliega una función desde el código fuente, la CLI de Google Cloud sube el directorio de origen (y todo lo que contiene) a Google Cloud para compilarlo. Para evitar enviar archivos innecesarios, puedes usar el archivo .gcloudignore
. Edita el archivo .gcloudignore
para ignorar directorios comunes como .git
y target/
. Por ejemplo, un archivo .gcloudignore
podría contener lo siguiente:
.git
target
build
.idea
Desplegar desde un archivo JAR
Puedes implementar un archivo JAR prediseñado que contenga la función. Esto resulta útil, sobre todo si necesitas desplegar una función que usa dependencias de un repositorio de artefactos privado al que no se puede acceder desde la canalización de compilación de Google Cloud al compilar desde el origen. El archivo JAR puede ser un uber JAR que contenga la clase de la función y todas sus clases de dependencia, o bien un archivo JAR ligero que tenga entradas Class-Path
para los archivos JAR de dependencia en el archivo META-INF/MANIFEST.MF
.
Compilar y desplegar un Uber JAR
Un uber JAR es un archivo JAR que contiene las clases de funciones, así como todas sus dependencias. Puedes crear un uber JAR con Maven y Gradle. Para desplegar un Uber JAR, debe ser el único archivo JAR de su directorio. Por ejemplo:
my-function-deployment/ ├─ my-function-with-all-dependencies.jar
Puedes copiar el archivo en esta estructura de directorios o usar los complementos de Maven y Gradle para generar el directorio de implementación correcto.
Maven
Usa el complemento Maven Shade para crear un archivo JAR grande. Configura tu
pom.xml
con el complemento 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 el uber JAR:
mvn package
A continuación, haz el despliegue con el siguiente comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=target/deployment
Gradle
Usa el complemento Shadow para Gradle. Configura el complemento en el archivo build.gradle
:
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() } ...
Ahora puedes ejecutar Gradle con el comando shadowJar
:
gradle shadowJar
A continuación, haz el despliegue con el siguiente comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=build/libs
Compilar y desplegar un archivo JAR ligero con dependencias externas
Puedes compilar y desplegar un archivo JAR ligero en lugar de un uber JAR. Un archivo JAR ligero es un archivo JAR que contiene solo las clases de funciones sin las dependencias insertadas en el mismo archivo JAR. Como las dependencias siguen siendo necesarias para la implementación, debes configurar los elementos de la siguiente manera:
- Las dependencias deben estar en un subdirectorio relativo al archivo JAR que se va a implementar.
- El archivo JAR debe tener un archivo
META-INF/MANIFEST.MF
que incluya un atributoClass-Path
cuyo valor enumere las rutas de dependencia necesarias.
Por ejemplo, tu archivo JAR my-function.jar tiene un archivo META-INF/MANIFEST.MF
que tiene 2 dependencias en el directorio libs/
(una lista de rutas relativas separadas por espacios):
Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar
El directorio de implementación debe contener el archivo JAR de la función principal, así como un subdirectorio con las dos dependencias de las que depende la función:
function-deployment/ ├─ my-function.jar ├─ libs ├─ dep1.jar ├─ dep2.jar
Puedes crear un archivo JAR ligero con Maven y Gradle:
Maven
Usa el complemento JAR de Maven para configurar automáticamente MANIFEST.MF
con las rutas de las dependencias y, a continuación, usa el complemento de dependencia de Maven para copiar las dependencias.
<?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>
Compila el JAR delgado:
mvn package
A continuación, haz el despliegue con el siguiente comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=target/deployment
Gradle
Actualiza el archivo de proyecto build.gradle
para añadir una nueva tarea que obtenga las dependencias:
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 } }