如何在 Kotlin 上创建 AWS Lambda 函数?

5
AWS Lambda函数是否支持Kotlin语言?目前Lambda函数创建向导中的运行时下拉列表中没有Kotlin选项。

enter image description here

但是有Java 8和不同的Node.js版本。在AWS Lambda上,使用Kotlin编写的函数应该选择哪个平台更合适 - JVM还是Node.js?并且我可以使用哪些Kotlin框架来编写Lambda函数?


1
AWS博客上有一篇关于Kotlin和Groovy JVM语言与AWS Lambda的文章:https://aws.amazon.com/blogs/compute/kotlin-and-groovy-jvm-languages-with-aws-lambda/ - matiit
@matiit谢谢您提供的链接! - Hleb
3个回答

10

Kotlin/JVM

在Kotlin上创建AWS Lambda函数最自然的方法是使用Kotlin/JVM并针对Java 8 Lambda运行时。 Kotlin与Java的互操作性非常好。JVM Lambda函数应该打包成fat JAR,即包含所有依赖项的JAR文件。使用Gradle很容易实现:

build.gradle.kts:

plugins {
    kotlin("jvm").version("1.3.41") // (1)
    id("com.github.johnrengelman.shadow").version("5.1.0") // (2)
}

repositories {
    jcenter()
}

dependencies {
    implementation(kotlin("stdlib-jdk8")) // (3)
    implementation("com.amazonaws:aws-lambda-java-core:1.2.0") // (4)
}

  1. 标准 Kotlin/JVM 插件 支持构建 JVM 构件
  2. Shadow 插件 用于生成 fat JAR
  3. Kotlin 的 stdlib 在运行时是必需的。这里我们使用一个由 JDK 8 编译的版本。
  4. 该构件 提供了一些接口 可以在 Java Lambda 函数中实现。

然后只需创建一个处理程序:

Handler.kt:

class Handler : RequestHandler<Input, Output> { // (1)
    override fun handleRequest(input: Input, context: Context): Output {
        println(input)

        return Output()
    }
}

  1. 该库为您提供了一个通用的RequestHandler类。您只需要实现它的单个方法handleRequest。输入和输出可以是您的POJO(POKO),只需确保它们可以使用Jackson进行序列化和反序列化(Lambda的文档没有明确提到,但如果出现问题,您将在日志中看到Jackson的提及);或原始类型;或一些预定义类。

在这里查看完整的代码示例:其中包含可与{{link3:API Gateway中的Lambda代理集成}}一起使用的函数。

对于Kotlin/JVM来说就是这样。非常简单。

Kotlin/JS

我不是Kotlin/JS的专家,但你也可以将目标设置为Node.js运行时,尽管这并不像JVM那样直观。

思路将会是将你的Kotlin代码编译(转换)成JavaScript,并将其部署为通常的JavaScript Lambda函数(即ZIP文件)。

处理程序可以如下所示:

Handler.kt

import kotlin.js.json

@JsName("handle")
fun handle(input: dynamic, context: dynamic): dynamic {
    println(JSON.stringify(input))

    val result: dynamic = json(
            "statusCode" to 307,
            "headers" to json(
                    "Location" to "https://google.com"
            )
    )

    return result
}

完整示例可以在这里找到。它与上面的Kotlin/JVM Lambda函数相同(响应重定向),但运行在Node.js 10.x运行时上。
对于Kotlin/JS,项目设置稍微困难一些:您需要将转换后的JS与依赖项(node_modules)打包到ZIP文件中。可能有很多方法可以做到这一点,您可以参考其中一个这里
奖励: Kotlin/Native!

亚马逊 宣布 Lambda Runtime API,这是在 AWS re:Invent 2018上发布的。它允许开发人员使用所谓的自定义运行时构建Lambda函数,使用他们想要的任何技术。是的,现在可以使用PHP、Perl、Pascal(有人用吗?)甚至Bash(他们在文档中使用它)编写函数了!

自定义运行时函数与普通函数的工作方式略有不同。运行时的工作是:

  1. 执行函数的初始化逻辑。对于Java来说,这意味着启动JVM,加载类并运行静态初始化器。
  2. 定位通过“Handler”配置参数传递的处理程序。
  3. 为每个传入事件执行处理程序。
这里有一张图片可以帮助你理解函数的生命周期:

Custom runtime lifecycle

一个非常基础的处理程序可能看起来像这样:

Handler.kt:

fun main() = runBlocking { // (1)
    val client = HttpClient(Curl) // (2)

    while (true) { // (3)
        val invocation = client.call("http://${getenv("AWS_LAMBDA_RUNTIME_API")!!.toKString()}/2018-06-01/runtime/invocation/next") {
            method = HttpMethod.Get
        } // (4)

        // (5)
        val invocationId = invocation.response.headers["Lambda-Runtime-Aws-Request-Id"]

        // (6)
        client.call("http://${getenv("AWS_LAMBDA_RUNTIME_API")!!.toKString()}/2018-06-01/runtime/invocation/$invocationId/response") {
            method = HttpMethod.Post
            body = TextContent(
                    "{\"statusCode\": 307, \"headers\": {\"Location\": \"https://google.com\"}}",
                    ContentType.Application.Json
            )
        }
    }
}
  1. 只要我们使用Ktor,就需要协程作用域。获取协程作用域的最简单方法是使用runBlocking
  2. 使用Curl引擎配置HTTP客户端。这是本文开头图片中的初始化阶段。
  3. 进入事件循环。
  4. 获取下一个要处理的事件。
  5. 解析事件。感觉比grep好,不是吗?
  6. 通过调用AWS的REST API来响应。

正如您所看到的,在Kotlin/Native中需要编写更多的代码。可以在这里查看完整的示例。


结论

如果您想要使用Lambda函数,可能不应该考虑Kotlin/JS和Kotlin/Native。

Kotlin/JS相对于JavaScript和TypeScript几乎没有提供更多的东西,但需要编写更多的代码才能达到相同的结果。面对JavaScript固有的动态性会带来一些痛苦,我认为 Kotlin/JS 的互操作性不如 Kotlin/JVM。构建过程也更加复杂,因为它需要配置 Gradle 和 NPM 一起工作(而 JS/TS 只需要 NPM,Kotlin/JVM 只需要 Gradle)。

Kotlin/Native需要你编写更多的代码来处理事件。此外,您将无法轻松地使用任何 AWS SDK:JVM库将无法与 Kotlin/Native 兼容(尽管您可能可以使用比 JVM 更低级别的 C/C++ SDK)。构建过程也更加复杂。

如果你有兴趣比较AWS Lambda的不同语言/运行时,请查看我在上面链接了几次的repo。它包括用Java、Kotlin/JVM、Kotlin/JS、Kotlin/Native、JS、Ruby、Python和Bash实现的Lambda。要了解有关AWS Lambdas的Kotlin/Native的更多信息,请在这里阅读。该文章还对不同语言的函数速度进行了比较。简而言之:
  1. Kotlin/Native性能不是很好。但它仍然优于冷启动JVM函数。
  2. Golang可能是Lambda函数寻求速度的最佳选择。
  3. 预热的JVM(Java和Kotlin)函数表现非常出色。
  4. Kotlin/JS提供良好的冷启动时间,但预热的脚本函数不如Golang和JVM。

6
在Javaland,如果你要将Kotlin程序放在服务器上,应该制作一个fat jar,这样就可以在任何JVM上执行它,而不必担心对Kotlin的显式支持。
或者,如果你不想支付AWS Lambda冷启动的JVM启动成本,你可以考虑使用针对Node.js运行时的Kotlin。但是我几乎会采取完全相同的方法:在构建服务器上将你的Kotlin编译为Javascript,打包你的(现在的)Javascripts + NPM模块,并将它们发送到Lambda。这可能会起作用,也可能不会,这取决于你的代码多少假定了Java包...
因此,我认为回答你的问题有两方面:
1. 你有多在意冷启动所需的时间?/ 您将多频繁地进行冷启动和暖请求?
2. 你的应用程序在多大程度上依赖于Java东西?
但在这两种情况下,你都不需要对Kotlin进行明确的支持,只需要你的编译过程生成的字节码(JVM或Javascript / Node)。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接