JVM 语言

您可以使用不同的 JVM 语言(如 KotlinGroovyScala)编写函数,只要它们符合以下规则即可:

  • 该函数是一个公共类,用于实现函数接口(HttpFunctionBackgroundFunctionRawBackgroundFunction)之一并具有公共无参数构造函数。

  • 如果您要从源代码部署:

    • 它可以从 Maven 构建。
    • 构建文件包含用于生成编译类的所有插件。
  • 如果您要从预构建 JAR 进行部署,请执行以下操作:

    • 您可以使用任何构建工具来生成此 JAR。
    • 预构建 JAR 必须是包含所有依赖项类的 Fat JAR,或其清单必须包含 Class-Path 条目以及这些依赖项类所在 jar 的相对位置。

HTTP 函数示例

如果要通过 HTTP(S) 请求调用您的函数,请使用 HTTP 函数。以下示例会输出 "Hello World!" 消息。

Kotlin

import com.google.cloud.functions.HttpFunction
import com.google.cloud.functions.HttpRequest
import com.google.cloud.functions.HttpResponse
import java.io.IOException
import java.util.logging.Logger

class HelloWorld : HttpFunction {
    // Simple function to return "Hello World"
    @Throws(IOException::class)
    override fun service(request: HttpRequest, response: HttpResponse) {
        response.writer.write("Hello World!")
    }
}

Groovy

import com.google.cloud.functions.HttpFunction
import com.google.cloud.functions.HttpRequest
import com.google.cloud.functions.HttpResponse

class GroovyHelloWorld implements HttpFunction {
    @Override
    void service(HttpRequest request, HttpResponse response) {
        response.writer.write("Hello World!")
    }
}

Scala

class ScalaHelloWorld extends HttpFunction {
  override def service(httpRequest: HttpRequest, httpResponse: HttpResponse): Unit = {
    httpResponse.getWriter.write("Hello World!")
  }
}

用于 HTTP 示例的 pom.xml 文件

以下是用于上述示例的 pom.xml 文件:

Kotlin

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-kotlin-hello-world</artifactId>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <kotlin.version>1.9.22</kotlin.version>
  </properties>

  <dependencies>
    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib-jdk8</artifactId>
      <version>${kotlin.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-test</artifactId>
      <version>${kotlin.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.HelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-maven-plugin</artifactId>
        <version>${kotlin.version}</version>
        <executions>
          <execution>
            <id>compile</id>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
            <configuration>
              <sourceDirs>
                <source>src/main/kotlin</source>
              </sourceDirs>
            </configuration>
          </execution>
          <execution>
            <id>test-compile</id>
            <phase>test-compile</phase>
            <goals>
              <goal>test-compile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <jvmTarget>1.8</jvmTarget>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Groovy

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-groovy-hello-world</artifactId>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <groovy.version>3.0.20</groovy.version>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <artifactId>libraries-bom</artifactId>
        <groupId>com.google.cloud</groupId>
        <scope>import</scope>
        <type>pom</type>
        <version>26.32.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- Required for groovy samples -->
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>${groovy.version}</version>
      <type>pom</type>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.GroovyHelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>groovy-compile</id>
            <phase>process-resources</phase>
            <goals>
              <goal>addSources</goal>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <!-- any version of Groovy \>= 1.5.0 should work here -->
            <version>${groovy.version}</version>
            <scope>runtime</scope>
            <type>pom</type>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

Scala

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-scala-hello-world</artifactId>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <artifactId>libraries-bom</artifactId>
        <groupId>com.google.cloud</groupId>
        <scope>import</scope>
        <type>pom</type>
        <version>26.32.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- Required for scala samples -->
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>2.13.5</version>
    </dependency>

    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.ScalaHelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>4.4.1</version>
        <executions>
          <execution>
            <id>scala-compile</id>
            <phase>process-resources</phase>
            <goals>
              <goal>add-source</goal>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

部署 HTTP 函数

Kotlin

gcloud functions deploy kotlin-helloworld --entry-point functions.KotlinHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

Groovy

gcloud functions deploy groovy-helloworld --entry-point functions.GroovyHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

Scala

gcloud functions deploy scala-helloworld --entry-point functions.ScalaHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

事件驱动的函数示例

如果您希望间接调用 Cloud Functions 函数来响应异步事件(例如,有关 Pub/Sub 主题的消息、Cloud Storage 存储分区的更改或 Firebase 事件),则使用事件驱动的函数。

事件驱动的函数有两种类型:后台函数和 CloudEvent 函数。JVM 语言仅支持后台函数

Kotlin

import com.google.cloud.functions.BackgroundFunction
import com.google.cloud.functions.Context
import functions.eventpojos.PubsubMessage
import java.nio.charset.StandardCharsets
import java.util.Base64
import java.util.logging.Logger

class KotlinHelloPubSub : BackgroundFunction<PubsubMessage> {
    override fun accept(message: PubsubMessage, context: Context) {
        // name's default value is "world"
        var name = "world"
        if (message?.data != null) {
            name = String(
                    Base64.getDecoder().decode(message.data!!.toByteArray(StandardCharsets.UTF_8)),
                    StandardCharsets.UTF_8)
        }
        LOGGER.info(String.format("Hello %s!", name))
        return;
    }

    companion object {
        private val LOGGER = Logger.getLogger(KotlinHelloPubSub::class.java.name)
    }
}

开发后台函数时,您可以为触发函数的事件定义类。但是,如果您的事件类不符合特定准则,则 GSON 编组就可能无法直接使用 Kotlin。

在 Kotlin 事件类中,属性必须符合以下准则:

  • 它们可以设置为 null
  • 系统不会为其指定默认值。
  • 它们不是委托属性。

另一种方法是使用 Java 创建事件类,并在 Kotlin 函数类中使用这些事件类。

Groovy

import com.google.cloud.functions.BackgroundFunction
import com.google.cloud.functions.Context
import functions.eventpojos.PubsubMessage
import java.nio.charset.StandardCharsets
import java.util.logging.Logger

class GroovyHelloPubSub implements BackgroundFunction<PubsubMessage> {
    private static final Logger LOGGER = Logger.getLogger(GroovyHelloPubSub.class.name)

    @Override
    void accept(PubsubMessage message, Context context) {
        // name's default value is "world"
        String name = "world"

        if (message?.data) {
             name = new String(Base64.decoder.decode(message.data), StandardCharsets.UTF_8)
        }

        LOGGER.info("Hello ${name}!")
        return
    }
}

Scala

import java.nio.charset.StandardCharsets
import java.util.Base64
import java.util.logging.Logger

import com.google.cloud.functions.{BackgroundFunction, Context}
import functions.eventpojos.PubsubMessage

class ScalaHelloPubSub extends BackgroundFunction[PubsubMessage] {

  val LOGGER = Logger.getLogger(this.getClass.getName)

  override def accept(message: PubsubMessage, context: Context): Unit = {
    // name's default value is "world"
    var name = "world"
    if (message != null && message.getData != null) {
      name = new String(Base64.getDecoder.decode(
        message.getData.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)
    }
    LOGGER.info(String.format("Hello %s!", name))
  }
}

部署后台函数

Kotlin

gcloud functions deploy kotlin-hello-pubsub --entry-point functions.KotlinHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

Groovy

gcloud functions deploy groovy-hello-pubsub --entry-point functions.GroovyHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

Scala

gcloud functions deploy scala-hello-pubsub --entry-point functions.ScalaHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

测试后台示例

您可以按如下方式测试后台示例:

  1. 向 Pub/Sub 主题发布消息以触发您的函数:

    gcloud pubsub topics publish my-topic --message Flurry
  2. 查看日志:

    gcloud functions logs read --limit 10

您应该会看到类似这样的内容,其中的一条消息包含您发布到 Pub/Sub 主题的名称:

D      my-function  ...  Function execution started
I      my-function  ...  Hello Flurry!
D      my-function  ...  Function execution took 39 ms, finished with status: 'ok'