基于函数计算的钉钉回调函数接口中使用钉钉回调函数案例实践了AWS Lambda无服务函数。该示例中,我们将自定义的函数代码及依赖的第三方库(比如json处理库jackson, 钉钉openapi加密库, aws dynamodb client等)整体打包为一个部署包,上传到lamdba代码仓库用于函数执行。

然而实际项目中,其实有大量的相关函数可能会共享这些基础依赖库、三方函数库(比如headless chrome(Puppeteer), pandoc, OCR library – Tesseract等等)或者使用自定义runtime(如官方未支持的java11)的需求。AWS Lambda在去年底发布了Lambda layers功能来满足上述这些实际开发中的需求。

接下来,让我们看看如何将前文中的函数依赖放置到一个单独的layer中,作为不同函数的共享依赖库。

在我们的构建配置build.gradle中,将函数的共享依赖拷贝到java runtime特定的目录结构java/lib/下,

153
154
155
156
157
tasks.register<Copy>("depsLayer") {
    into("$buildDir/deps/java/lib")
    from(configurations.compileClasspath.get())
    from(configurations.runtimeClasspath.get())
}

接下来将共享的依赖创建为一个lambda layer,并且让callback函数依赖这个共享layer,不再将所有的依赖打包为一个很大的部署包减小每次变更需要发布的包大小。

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  DependenciesLayer:
    Type: AWS::LayerVersion
    Properties:
      LayerName: DingTalkDependencies
      Description: DingTalk Dependencies Layer
      ContentUri: 'build/deps'
      CompatibleRuntimes:
        - java8
      LicenseInfo: 'Available under the MIT-0 license.'
      RetentionPolicy: Retain

  CallbackFunction:
    Type: AWS::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: build/libs/dingtalk-callback-1.0.0-SNAPSHOT.jar
      Handler: com.github.zxkane.dingtalk.Callback::handleRequest
      Layers:
        - !Ref DependenciesLayer
      Policies:

在console查看部署后的函数,如下图,可以看到函数新增了一个layer。

lambda with layers

同其他的语言、技术一样,Awesome Layers项目收集了目前一些常用且维护较好的layer,自创轮子之前可以先参考下😀。

使用layer同样有以下限制,使用前需要注意,

  • 依赖的layer数不能超过5个
  • 函数以及依赖的所有layers解压后不可以超过250MB