尝试用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 屏幕在管理控制台上将以以下方式显示。
如果您想通过管理控制台进行设置,可以通过上述画面中的”添加图层”选项自行进行设置。
执行这个函数时,
输出了一条日志。
太棒了!
对于实际的使用方法的思考
好的,我明白了Lambda Layers可以用Golang实现,但实际上它是否有用呢?
首先,就像这里所述一样,它有很多异常的限制。
-
- Layer と Function で Golang のコンパイラバージョンが一致している必要がある
- Layer と Function が同じパッケージを使っている場合、そのバージョンが一致している必要がある
嗯,如果在部署 Layer 函数之后立即应用它,可能会导致它无法正常工作。
这种情况也存在,Lambda Layer在部署后,并不会自动切换调用方的Lambda函数,而且看起来也没有像$ LATEST或别名那样的存在。
然而,共享库是这样的吗?C语言的共享库就算有问题,只需要修正库本身的定义就可以解决。
嗯,从AWS的角度和Golang的思想来看,如果要修复共通处理,可能是在调用点进行CI / CD并部署的意思。那么,像我一开始写的那样,使用Git Submodules或本地Git存储库似乎是个不错的选择。但是,如果这样做的话,在Golang中Lambda Layers的角色是什么呢?也许是不必要的吗……。