Java 部署選項

部署 Java 函式的做法有兩種:

從原始碼部署

函式的原始碼必須位於 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/SubGoogle Cloud Storage

從來源部署函式時,Google Cloud CLI 會將來源目錄 (以及其中的所有內容) 上傳至 Google Cloud 進行建構。為避免傳送不必要的檔案,您可以使用 .gcloudignore file。編輯 .gcloudignore 檔案,忽略 .gittarget/ 等常見目錄。例如,.gcloudignore 檔案可能包含下列內容:

.git
target
build
.idea

從 JAR 部署

您可以部署含有函式的預先建構 JAR。這項功能特別適用於您需要部署函式,而該函式會使用私人構件存放區的依附元件,且無法從 Google Cloud 的建構管道存取。JAR 可以是超級 JAR,其中包含函式類別及其所有依附元件類別,或是精簡 JAR,其中包含 META-INF/MANIFEST.MF 檔案中依附元件 JAR 的 Class-Path 項目。

建構及部署 Uber JAR

uber JAR 是包含函式類別及其所有依附元件的 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

建構及部署含有外部依附元件的薄 JAR

您可以建構及部署精簡 JAR 檔案,而非 uber JAR。精簡 JAR 檔案是指只含有函式類別,而沒有在同一個 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 建構精簡 JAR:

Maven

使用 Maven JAR 外掛程式,自動設定 MANIFEST.MF 與依附元件的路徑,然後使用 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>

建構精簡 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
 }
}