Java 部署选项
您可以通过以下两种方式部署 Java 函数:
- 从源代码部署。如需大致了解从源代码部署,请参阅部署指南。
- 从预封装的 JAR 文件部署。
从源代码部署
函数的源代码必须位于 Maven 项目的常规位置 (src/main/java
)。本文档中的示例函数直接位于 src/main/java
中,.java
源文件中没有软件包声明。对于非常重要的代码,则可能要引入软件包。如果该软件包为 com.example
,则层次结构如下所示:
myfunction/ ├─ pom.xml ├─ src ├─main ├─ java ├─ com ├─ example ├─ MyFunction.java
使用以下命令部署 HTTP 函数:
gcloud functions deploy $name \ --trigger-http \ --gen2 \ --region=REGION \ --entry-point $function_class \ --runtime java17
其中:
$name
是任意的描述性名称,是部署后的函数名称。$name
只能包含字母、数字、下划线和连字符。$function_class
是类的完全限定名称(例如com.example.MyFunction
,如果您不使用软件包,则为MyFunction
)。
使用以下命令部署事件驱动型函数:
gcloud functions deploy $name \ --entry-point $function_class \ --gen2 \ --region=REGION \ --trigger-resource $resource_name \ --trigger-event $event_name \ --runtime java17
其中:
$name
是任意的描述性名称,是部署后的函数名称。$function_class
是类的完全限定名称(例如com.example.MyFunction
,如果您不使用软件包,则为MyFunction
)。$resource_name
和$event_name
特定于触发事件驱动函数的事件。例如,受支持的资源和事件可以是 Google Cloud Pub/Sub 和 Google Cloud Storage。
从源代码部署函数时,Google Cloud CLI 会将源目录(以及其中的所有内容)上传到 Google Cloud 以进行构建。为避免发送不必要的文件,您可以使用 .gcloudignore
文件。修改 .gcloudignore
文件以忽略 .git
和 target/
等常用目录。例如,.gcloudignore
文件可能包含以下内容:
.git
target
build
.idea
从 JAR 部署
您可以部署包含该函数的预构建 JAR。如果您需要部署使用来自私有工件代码库(从源代码构建时,无法从 Google Cloud 的构建流水线访问该代码库)的依赖项的函数,这将非常有用。JAR 可以是包含函数类及其所有依赖项类的超级 JAR,也可以是在 META-INF/MANIFEST.MF
文件中具有依赖项 JAR 的 Class-Path
条目的精简 JAR。
构建和部署超级 JAR
超级 JAR 文件包含函数类及其所有依赖项。您可以使用 Maven 和 Gradle 构建超级 JAR。如需部署超级 JAR,它必须是自己的目录中唯一的 JAR 文件,例如:
my-function-deployment/ ├─ my-function-with-all-dependencies.jar
您可以将文件复制到此目录结构,也可以使用 Maven 和 Gradle 插件生成正确的部署目录。
Maven
使用 Maven Shade 插件构建超级 JAR。使用 Shade 插件配置 pom.xml
:
<?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>
构建 Uber JAR:
mvn package
然后使用以下命令进行部署:
gcloud functions deploy jar-example \ --gen2 \ --entry-point=Example \ --runtime=java17 \ --region=REGION \ --trigger-http \ --source=target/deployment
Gradle
使用 Gradle 的 Shadow 插件。在 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() } ...
现在,您可以使用 shadowJar
命令运行 Gradle:
gradle shadowJar
然后使用以下命令进行部署:
gcloud functions deploy jar-example \
--entry-point=Example \
--runtime=java17 \
--trigger-http \
--source=build/libs
构建和部署使用外部依赖项的精简 JAR
您可以构建和部署一个精简 JAR 文件,而不是超级 JAR。精简 JAR 文件仅包含函数类,不包含嵌入到同一 JAR 文件中的依赖项。由于部署仍需要依赖项,因此您需要按如下所示进行设置:
- 依赖项必须位于要部署的 JAR 的相对子目录中。
- JAR 文件必须具有一个
META-INF/MANIFEST.MF
文件,其中包含的Class-Path
属性的值列出所需的依赖项路径。
例如,您的 JAR 文件 my-function.jar 的 META-INF/MANIFEST.MF
文件在 libs/
目录中有两个依赖项(以空格分隔的相对路径的列表):
Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar
然后,您的部署目录应包含主函数 JAR 文件,以及包含函数依赖的两个依赖项的子目录:
function-deployment/ ├─ my-function.jar ├─ libs ├─ dep1.jar ├─ dep2.jar
您可以使用 Maven 和 Gradle 构建精简 JAR:
Maven
使用 Maven JAR 插件自动为 MANIFEST.MF
配置依赖项路径,然后使用 Maven Dependency 插件复制依赖项。
<?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>
构建精简 JAR:
mvn package
然后使用以下命令进行部署:
gcloud functions deploy jar-example \ --gen2 \ --region=REGION \ --entry-point=Example \ --runtime=java17 \ --trigger-http \ --source=target/deployment
Gradle
更新 build.gradle
项目文件以添加新的任务以提取依赖项:
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 } }