Serverless Framework是一个开源命令行工具。他提供函数脚手架、流程自动化、最佳实践等帮助开发、部署跨云厂商的托管无服务器计算服务(官方已支持aws, Azure, GCP, IBM Cloud等各种厂商的无服务器计算)。同时支持使用插件来扩展各种功能,比如支持更多云厂商无服务器计算服务,例如阿里云的函数计算

这里使用基于函数计算的钉钉回调函数接口示例来演示如何使用Serverless Framework将一个无服务器函数部署到AWS Lambda

安装servereless后,可以通过serverless create命令创建函数脚手架工程,或者在已有工程的下创建serverless配置文件serverless.yml

接下来可以参考serverless aws reference配置你的aws lambda函数及需要的各种资源。如果已经有过使用AWS CloudFormation或者AWS SAM经验的,可以很快适应编写Serverless配置。Serverless的配置本质上是将CloudFormation/SAM相关的概念进行抽象,为各个云厂商的无服务器计算服务提供统一的工具、命令以及概念抽象。在部署aws lambda时,serverless配置会被转换为CloudFormation配置,通过AWS API进行创建或变更。

对于Dingtalk Callback on AWS Lambda, serverless配置声明如下。其中指定了service的基本信息,全局的配置(如stage、region等)、云厂商provider(这里是aws)。函数的基本信息、权限、layer、触发器,自定义layer以及其他云厂商资源,比如Dingtalk callback这里用到的DynamoDB。完整的serverless配置查看这里

service:
  name: dingtalk-callback

frameworkVersion: ">=1.0.0 <2.0.0"

provider:
  name: aws
  runtime: java8
  stage: ${opt:stage, 'dev'} # Set the default stage used. Default is dev
  region: ${opt:region, 'ap-southeast-1'} # Overwrite the default region used. Default is ap-southeast-1
  profile: ${opt:profile, 'default'} # The default profile to use with this service
  versionFunctions: true # Optional function versioning
  endpointType: regional # Optional endpoint configuration for API Gateway REST API. Default is Edge.

functions:
  dingtalk-callback:
    handler: com.github.zxkane.dingtalk.Callback::handleRequest # required, handler set in AWS Lambda
    name: ${self:provider.stage}-dingtalk-callback # optional, Deployed Lambda name
    memorySize: 384 # optional, in MB, default is 1024
    timeout: 15 # optional, in seconds, default is 6
    environment: # Function level environment variables
      PARA_DD_TOKEN: DD_TOKEN
      TABLE_NAME: {Ref: BPMTable}
    package:
      artifact: build/libs/dingtalk-callback-1.0.0-SNAPSHOT.jar
    role: dingtalkCallbackIAMRole
    layers: # An optional list Lambda Layers to use
      - {Ref: DependenciesLambdaLayer}
    events: # The Events that trigger this Function
      - http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function.  Learn more in "events/apigateway"
          path: dingtalk # Path for this endpoint
          method: post # HTTP method for this endpoint

layers:
  dependencies:
    path: build/deps

resources:  # CloudFormation template syntax
  Resources:
    dingtalkCallbackIAMRole:
      Type: AWS::Role
      Properties:
        Policies:
          - PolicyName: SSMPolicy
          - PolicyName: DynamoDBPolicy
    BPMTable:
      Type: AWS::Table
      Properties:
        TableName: bpm_raw_${self:service.name}_${self:provider.stage}
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

对于使用单一云厂商无服务器计算并且已经使用了类似sam cli实现持续集成、持续部署的用户,Serverless Framework并不能带来更多生产力的提升,在稳定性(封装云厂商的功能,增加复杂度很可能引入新的问题)或功能的及时性上可能还不如云厂商提供的工具。

对于有多云厂商部署无服务器函数需求的用户,使用了Serverless Framework并不能轻松的将无服务器函数部署到不同云厂商的托管服务上,他只是帮助提供跨云厂商的统一工具链及相似的持续集成、部署等最佳实践流程。例如将一套函数从AWS迁移到Azure上,需要重新实现Azure provider下的配置,因为云厂商的托管无服务器服务和其他云资源都存在着大量差异。另外函数代码也需要面临改造,不同云厂商的触发器消息事件也都有不同的格式!这里可以考虑使用类似Spring Cloud Function这样的解决方案来实现跨云厂商的函数编写。

总之,Serverless Framework对于跨云厂商部署场景有一定生产效率的提升,但他离完美解决跨云厂商无服务器托管服务(各厂商服务天生不兼容)还有很远的距离,也许这个思路就是走不通的😕。