由於企業內部管理的需要,用到了釘釘的業務事件回調能力,正好將這個輕量級的接口使用無服務器技術來實現部署,以應對流量無規律下的動態擴展伸縮、按需使用、按量計費等需求。
阿里雲函數計算版本
由於公司系統部署在阿里雲,首先選擇使用阿里雲函數計算來實現及部署。該接口使用了JVM上語言Kotlin開發,雖然阿里雲函數計算官方支持的開發語言有Java但沒有Kotlin。其實無論Java或Kotlin最終部署文件都是Java Class字節碼,加上Kotlin與Java良好的互操作性,實測函數計算可以完美支持Kotlin開發(個人認爲任意JVM上的開發語言都是支持的)。
同時該函數使用了表格存儲來持久化回調事件。表格存儲是個按量計費的分佈式存儲,有興趣的可以自行查閱文檔瞭解更多。
該函數通過API網關和表格存儲觸發器來觸發。訪問日誌和執行日誌被存儲在日誌服務中。
函數的本地測試和線上部署,使用了函數計算提供的命令行工具Fun。基於Fun定義的阿里雲Serverless模型實現了對函數們使用資源的聲明和編排,集成Gitlab CI實現了函數的CI/CD自動化發佈流程。
不涉及公司業務的代碼已開源在Github,有興趣的可以作爲參考。
目前函數計算和表格存儲有各自的免費配額,在業務量不大的情況下,該服務完全免費。
AWS Lambda版本
AWS Lambda是目前全球使用最爲廣泛的serverless服務,同時也是函數計算髮展方向的引領者。
由於一些個人原因,筆者最近接觸了部分AWS服務,同時嘗試將釘釘回調函數移植到了AWS Lambda上。阿里雲上使用的雲服務改爲由AWS上對應服務來實現,例如存儲使用了DynamoDB,日誌使用CloudWatch收集和查詢。
本地測試和部署工具,使用的是SAM CLI,持續集成和持續部署使用的是AWS CodeBuild和AWS CodePipeline。此外AWS通過AWS CloudFormation提供一種非常強大的能力,可以將AWS上的各種資源通過配置聲明的方式來管理(也就是現在非常熱門的一個概念--Infrastructure as Code)。AWS CloudFormation會爲每次一個或多個資源的變更生成ChangeSet,提供查看對比、版本管理、遇到變更錯誤整體回退等能力。所以,AWS版本也將該項目的CI/CD部署用到的AWS CodeBuild、AWS CodePipeline、Amazon DynamoDB等資源通過CloudFormation的配置管理起來。
配置代碼段如下,
Description: Create a CodePipeline to include Github source, CodeBuild and Lambda deployment.
Parameters:
AppBaseName:
Type: String
Description: App base name
Default: dingtalk-callback
ArtifactStoreS3Location:
Type: String
Description: Name of the S3 bucket to store CodePipeline artificat.
BranchName:
Description: GitHub branch name
Type: String
Default: master
RepositoryName:
Description: GitHub repository name
Type: String
Default: dingtalk-callback-on-aws
GitHubOAuthToken:
Type: String
NoEcho: true
Resources:
BuildDingtalkProject:
Type: AWS::CodeBuild::Project
Properties:
Name:
Fn::Sub: ${AppBaseName}-build-${AWS::StackName}
Description: Build, test, package dingtalk callback project
ServiceRole:
Fn::GetAtt: [ CodeBuildRole, Arn ]
Artifacts:
Type: S3
Location:
Ref: ArtifactStoreS3Location
Name:
Fn::Sub: ${AppBaseName}-build-${AWS::StackName}
NamespaceType: BUILD_ID
Path:
Fn::Sub: ${AppBaseName}/artifacts
Packaging: NONE
OverrideArtifactName: true
EncryptionDisabled: true
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/java:openjdk-11
PrivilegedMode: false
ImagePullCredentialsType: CODEBUILD
EnvironmentVariables:
- Name: s3_bucket
Value:
Ref: ArtifactStoreS3Location
Source:
DingtalkCallbackPipeline:
Type: 'AWS::CodePipeline::Pipeline'
Properties:
Name:
Fn::Sub: ${AppBaseName}-pipeline-${AWS::StackName}
RoleArn:
Fn::GetAtt: [ CodePipelineRole, Arn ]
Stages:
- Name: Source
Actions:
- Name: SourceAction
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: 1
Provider: GitHub
OutputArtifacts:
- Name:
Fn::Sub: ${AppBaseName}-source-changed
Configuration:
Owner: !Ref GitHubOwner
Repo: !Ref RepositoryName
Branch: !Ref BranchName
OAuthToken: !Ref GitHubOAuthToken
PollForSourceChanges: false
RunOrder: 1
- Name: Build
Actions:
- Name: Build_Test_Package
InputArtifacts:
- Name:
Fn::Sub: ${AppBaseName}-source-changed
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
OutputArtifacts:
- Name:
Fn::Sub: ${AppBaseName}-packaged-yml
Configuration:
ProjectName:
Ref: BuildDingtalkProject
RunOrder: 1
AWS版本完整的代碼、CloudFormation配置以及部署文檔可以通過這裏查看。