尝试用Golang来实现Lambda Layers

首先

提到Lambda的共同处理,我们可以说是使用Lambda Layers。

让我们来确认和探讨一下使用 Lambda Layers 进行共享的感受,尽管 Golang 还有其他几种处理共享模块的方式(如使用 Git Submodules 或使用本地的 Git 仓库,请参考过去的文章)。

使用 Go 插件包

如果您在Golang中使用Lambda层,则需要使用Plugin包。
首先,让我们了解一下这个模块。

请查阅官方渠道以获取包装说明。

让我们来创建一个名为mylogger的插件来输出日志。

package main

import (
    "log"
)

func OutputLog(str string) {
    log.Printf(str)
}

请将其编译为 .so 格式进行输出。

$ GOOS=linux go build -buildmode=plugin -o mylogger.so

试着实现调用模块的来源。

package main

import (
    "log"
    "os"
    "plugin"
)

var (
    outputLog plugin.Symbol
)

func init() {
    var (
        pi  *plugin.Plugin
        err error
    )

    if pi, err = plugin.Open("mylogger.so"); err != nil {
        log.Printf("plugin Open() error: %s", err.Error())
        os.Exit(-1)
    }
    if outputLog, err = pi.Lookup("OutputLog"); err != nil {
        log.Printf("plugin Lookup() error: %s", err.Error())
        os.Exit(-1)
    }
}

func main() {
    outputLog.(func(string))("Hello Golang Plugin!!")
}

使用插件包的Open功能来打开共通库,并使用Lookup功能从共通模块中加载函数(确切地说,还可以加载变量。简而言之,加载符号变量的类型(plugin.Symbol))。

然后,编译此主要文件并在存放mylogger.so的目录中运行。

2020/11/01 11:55:27 Hello Golang Plugin!!

输出为。

在使用Lambda层的情况下

使用Lambda层时,共享模块的代码不需要做任何特殊修改。

根据您提供的信息,似乎 Lambda Layers 将会解压到 /opt 目录下,因此需要在 Lambda 函数中进行处理。

    if pi, err = plugin.Open("/opt/mylogger.so"); err != nil {

我会叫他过来。

还有,需要在Lambda上设置Lambda Layers。
在这个例子中,我们使用Terraform。

################################################################################
# Lambda                                                                       #
################################################################################
resource "aws_lambda_function" "test" {
  depends_on = [
    aws_cloudwatch_log_group.lambda,
  ]

  function_name    = local.lambda_function_name
  filename         = data.archive_file.main.output_path
  role             = aws_iam_role.lambda.arn
  handler          = "lambda_function"
  source_code_hash = data.archive_file.main.output_base64sha256
  runtime          = "go1.x"

  memory_size = 128
  timeout     = 30

  layers = [
    aws_lambda_layer_version.test.arn,
  ]
}

################################################################################
# Lambda Layer                                                                 #
################################################################################
resource "aws_lambda_layer_version" "test" {
  layer_name       = local.lambda_layer_name
  filename         = data.archive_file.layer.output_path
  source_code_hash = data.archive_file.layer.output_base64sha256
}

使用aws_lambda_layer_version的资源在aws_lambda_function的layers块中进行设置。

如果正确设置,Lambda 屏幕在管理控制台上将以以下方式显示。

キャプチャ1.png

如果您想通过管理控制台进行设置,可以通过上述画面中的”添加图层”选项自行进行设置。

执行这个函数时,

キャプチャ2.png

输出了一条日志。
太棒了!

对于实际的使用方法的思考

好的,我明白了Lambda Layers可以用Golang实现,但实际上它是否有用呢?
首先,就像这里所述一样,它有很多异常的限制。

    • Layer と Function で Golang のコンパイラバージョンが一致している必要がある

 

    Layer と Function が同じパッケージを使っている場合、そのバージョンが一致している必要がある

嗯,如果在部署 Layer 函数之后立即应用它,可能会导致它无法正常工作。

这种情况也存在,Lambda Layer在部署后,并不会自动切换调用方的Lambda函数,而且看起来也没有像$ LATEST或别名那样的存在。
然而,共享库是这样的吗?C语言的共享库就算有问题,只需要修正库本身的定义就可以解决。

嗯,从AWS的角度和Golang的思想来看,如果要修复共通处理,可能是在调用点进行CI / CD并部署的意思。那么,像我一开始写的那样,使用Git Submodules或本地Git存储库似乎是个不错的选择。但是,如果这样做的话,在Golang中Lambda Layers的角色是什么呢?也许是不必要的吗……。

广告
将在 10 秒后关闭
bannerAds