在建造Lambdas时选择去
#aws #serverless #lambda #go

因此,您决定使用AWS构建第一个或第500 lambda功能。恭喜!这本身就是一个很好的决定,它将为您奠定卓越的卓越运营,易于维护,灵活性的稳定基础,以及无服务器随附的许多其他阳性。现在,您要在哪种语言中开发这种新的lambda?我一直是在建造Lambdas时选择Go的巨大支持者,我想让您了解为什么。

选择lambda运行时间

当您开始构建第一个lambda时,该运行时间的决定必须是您决定的第一件事之一。当前,AWS支持许多可以在AWS Runtimes lambda页面上探索的不同选项。与Lambdas一起建造的最好的事情之一是,由于您的问题范围几乎隔离到“纳米”级别,因此您可以将自己置于仅锁定成一组技术中。

我的意思是,某些语言和框架更适合解决某些问题,您可以使用一组功能探索这些解决方案,同时继续在另一组完全不同的技术和框架中构建其他功能。而且,如果您发现这个兰巴达并没有表现出您的预期,那么时间和能源投资应该足够低,以至于移植到其他东西并不是世界末日。我已经看到在我的无服务器建筑物中发生了几次。

每个语言和框架都会影响您功能的配置文件。诸如:

之类的东西
  • 寒冷开始 - 部署Lambda并最初运行的时间
  • 成本 - 每GB秒价格。本质上分配了内存和时间组件
  • 内存 - 您的函数需要分配多少内存才能运行良好
  • 捆绑尺寸 - 束越大,部署的时间越长,启动时间

在建造Lambdas时选择去

首先,这纯粹是根据我的经验和意见的原因列表。我已经在GO,Node,.Net Core,Java,Python和Rust中部署了Lambdas,诚实地,您可以通过选择的任何语言获得成功。但是以下是我在构建功能时首先要伸手去拿的原因。

开发人员的经验

我明白了,这是主观的,但这又是一个意见。对我来说,内置的GO工具和标准库的广度对我来说就足够了。如此小的细节得到了照顾。

测试

我不需要选择摩卡咖啡,开玩笑,朱尼特(Junit),尼尼特(Nunit)或其他一些外部图书馆来运行我的GO单元测试。它内置在堆栈中

package sample
import "testing"

func Test_Should_Do_Something(t *testing.T) {
    if someCondition {
        t.Fail()
    }
}

然后能够运行go test,就是这样。

标准库

喜欢与否,API世界在JSON上运行。 Go拥有与JSON打交道的内置图书馆的本地支持。它的encoding包装非常全面,电线上和关闭物体的所有MarshallingUnmarshalling似乎都以相同的方式工作

package sample
import "encoding/json"

// unmarhsall
i := SomeStruct{}
err := json.Unmarshal(bytes, &i)

// marshall
i := SomeStruct{}
out, err := json.Marshal(&i)

当您在AWS生态系统中使用SQS,Step函数,DynamoDB和其他服务时,该本地功能将派上用场。

建筑物去

GO的构建过程很快。开发功能时为什么这很重要?反馈。当然,IDE和VSCODE非常擅长识别问题,但是如果您没有编译时间问题,并且只想开始运行代码,那么速度很重要。每天建造和测试几十次,您获得的节省将使您只能做几个循环。

我认为这是用现代语言低估的,从开始开始构建一种迅速编译的语言。如果您在API中说的是10或15个功能,则在使用CDK或SAM时,这也可以进行本地开发以及构建和部署。在本地启动API之前,它会迅速编译以节省您可以花在代码上的宝贵时间。

代码格式

Go fmt我几乎可以通过说明这一点。但是,要阐述一点,我看到了代码库的格式是强烈争辩的东西,要么只是保留了任何东西,因此代码库永远不会格式化。使用Go FMT,您有一种社区支持的方式来格式化代码,以使其看起来总是相同的,无论其来自何处。您的IDE具有支持,命令行具有一个工具,因此您不必考虑它。这比您想象的要大。

干净尚未详细语法

go具有熟悉的语法。除了所有常用的循环和控制构建体外,您还会注意到{}()之类的东西。评论看起来像C和C ++。该语言有时可能是一个触摸词,但是一旦您习惯了它,它就会有很多意义。特别是在错误管理方面。
Go缺乏继承,但它具有强大的界面设计弥补了它,并喜欢利用结构的组成,一旦您围绕模式包裹了一些清洁和强大的代码。

返回多个值的能力。一开始这似乎很奇怪,但是我发现func的所作所为更为明显,而不是构建一个持有我的返回对象的班级。采用此代码:

public class SomeClass {
    public String theString;
    public Integer theInteger
}

function SomeFunction() SomeClass {
    return new SomeClass() {
        theString: "ABC",
        theInteger 123
    };
}

对我来说,这几乎不像此代码那样可读

func SomeFunction() (string, int) {
    return "ABC", 123
}

这是函数返回的内容,并使我免于避免构建单独的“数据载波”以返回我的输出。或更糟糕的是,要有某种“参考”,即入站值会更改并突变某些从客户端隐藏的状态。

CDK支持

如果您不熟悉CDK,则here是一篇很好的介绍文章,可以使您入门。

构建基础架构作为代码具有很多好处,并且使用CDK几乎使其令人愉快。幸运的是,现在正在建立对CDK的支持。您可以通过使用GoFunction构造来声明将为正确的Lambda架构构建的函数。

new GoFunction(this, "TheFunc", {
    entry: path.join(__dirname, "some-path"),
    functionName: "func-name",
});

请查看documentation的更多CDK选项。

以上只是我喜欢与Lambdas外面一起工作的几个原因。

操作经验

束大小

让我们回到捆绑尺寸。这很重要,原因有两个。

  1. 部署时间。捆绑包越小,构建和部署的速度就越快。如果您的捆绑包为540MB vs说13MB,那么将您的档案推向Lambda环境的时间少得多
  2. 冷启动。同样,较小的捆绑包和较少的依赖项将大有帮助启动您的运行时。将所有内容都汇集到二进制中,快速启动超级启动,因此您会获得良好而快速的冷启动。

下面是lambda的一个实例,其中有一些事情正在发生,其中包括与DynamoDB和参数存储合作的AWS SDK的依赖关系,但捆绑包大小仅为13MB。我喜欢!

Bundle Size

寒冷开始

这是无服务器世界中的热门话题。我已经部署了Lambdas的6年来生产,我可以说,一开始,使用.NET Core,我将获得2-4秒的冷启动。对于异步型操作,这不是世界的尽头。但是,如果您的活动附加到API网关,用户是否想等待您的第一个回复?可能不是。

快速前进的几年,老实说,每种语言都有改进的进步,随着Snapstart的引入,Java现在在这些类型的用例中很愉快。我仍然更喜欢使用GO,因为下图显示了API端点上价值4天的冷启动潜伏期。平均水平超过500ms,对我来说,这是100%可以接受的,因为带有API网关的完整生命周期将低于1秒,这实现了我的个人目标,即让事情从API端点返回的情况下,以不到1秒的阈值。<<<<<<<<<<<<<<<<<<<<<<<<<< /p>

Threshold

我将其归因于捆绑包很小的GO的性质,依赖项已编译为“依赖”,并且启动应用程序只是“活泼的”。当提供GO支持时,我将成为第一个跳上快照火车的人之一,但就目前而言,我对此感到非常高兴。

运行时复杂性

这是超级主观的,我辩论将其放进去,但我喜欢Lambdas的另一件事,但也不喜欢层。层是一种在具有相似目的的功能上共享逻辑的好方法。但是另一方面,我发现他们可以从我身上隐藏东西,并且测试可能有些棘手。

通过使用GO,我将依赖项编译在其中,因此我发现可重复使用的代码是通过软件包依赖项共享的,我可以在我进行建筑物时在本地测试。同样,这不是世界上最大的事情,但是在构建功能时,我确实会更加熟悉。

可观察性

这并不是唯一的,但是这是我写的有关使用Go with Datadog的文章,它显示了将可观察性融入您的功能

的清洁和简单。

包起来

编码和部署lambdas是一段有意义的旅程,不必专注于不会为客户和最终用户带来价值的事物。通过关注重要的事情,您可以在想法上进行创新和迭代,而不是花时间在运营基础架构等工作或试图弄清楚如何在最理想的技术堆栈中构建功能。

lambdas和功能为您提供了最小的隔离水平,因此您可以专注于该问题,并选择最佳技术来实现一组功能。默认情况下,我抓住了我上面向您展示的原因。我知道这不是选择如何部署lambda的最受欢迎的运行时间,但我希望本文为您下次启动新功能时提供一些考虑。