Java 部署選項
Java 函式有兩種部署方法可供選擇:
- 從來源部署。相關主題概述請參閱「部署 Cloud 函式」。
- 從預先封裝的 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 --no-gen2 \
--entry-point $function_class --runtime java17
其中:
$name是任意的描述性名稱,部署後就成為函式名稱。$name只能使用英文字母、數字、底線和連字號。$function_class是類別的完整名稱 (例如com.example.MyFunction,如未使用套件則為MyFunction)。
使用下列指令部署事件導向函式:
gcloud functions deploy $name --no-gen2 --entry-point $function_class \
--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 可以是包含函式類別和所有依附元件類別的 uber JAR,或是在 META-INF/MANIFEST.MF 檔案中含有依附元件 Class-Path 條目的 thin JAR。
建構及部署 Uber JAR
Uber JAR 檔案包含函式類別和所有依附元件。您可以使用 Maven 和 Gradle 來建構 uber JAR。如要部署 Uber JAR,其必須為自身目錄中唯一的 JAR 檔案,例如:
my-function-deployment/ ├─ my-function-with-all-dependencies.jar
您可以將檔案複製到這個目錄結構中,也可以使用 Maven 和 Gradle 外掛程式產生正確的部署目錄。
Maven
使用 Maven Shade 外掛程式建構 uber 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 \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--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 \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=build/libs
建構及部署含有外部依附元件的 thin JAR
除了 uber JAR 以外,也可以改為建構並部署 thin JAR 檔案。Thin JAR 檔案只包含函式類別,不含內嵌在同一 JAR 檔案中的依附元件。由於部署作業仍需要依附元件,因此必須按照下列方式設定:
- 依附元件必須位於部署目標 JAR 的相對子目錄中。
- JAR 必須有
META-INF/MANIFEST.MF檔案,其中包含Class-Path屬性,而該屬性值會列出必要依附元件路徑。
例如,JAR 檔案 my-function.jar 含有 META-INF/MANIFEST.MF 檔案,其在 libs/ 目錄中有 2 個依附元件 (以半形空格分隔的相對路徑清單):
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 來建構 thin 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>
建構 thin JAR:
mvn package
然後使用下列指令部署:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--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
}
}