Alibaba Cloud Function Computeのトリガーを全種試す
はじめに
本稿は株式会社オープンストリーム Advent Calendar 2019の14日目です。
図らずも二年連続で14日目だったので今年はあえてこの日を選びました。とはいえ深い意味はありません。
Alibaba CloudのFunction Computeはフルマネージ型の関数実行サービスです。AWSでいうところのLambdaですね。
さまざまなイベントトリガーをサポートしているので全種試してみたいと思います。
それぞれイベントがどのような形式で送信されるのか見ていきましょう。
トリガー一覧
Function Computeの関数の設定から指定できるトリガーの種類は下記のとおりです。
- OSSトリガー
- Log Serviceトリガー
- タイムトリガー
- CDNトリガー
- Table Storeトリガー
- MNSトリガー
これらに加え、作成時のみ設定可能なHTTPトリガーと、連携元の方で設定されるAPI Gatewayトリガーがあるため全部で8種類です。
関数
今回用意した関数は以下の通りです。
'use strict';
exports.dump = (event, context, callback) => {
console.log('event:', event.toString());
const response = {
statusCode: 200,
body: event.toString(),
};
callback(null, response);
};
イベントをログ出力するだけの単純なものです。Node.jsの場合event
はBufferで渡される場合もあるのでtoString()
を呼んでいます。response
はAPI Gatewayトリガーを意識してのものです。他のトリガーでは使いません。
この関数をServerless Frameworkでデプロイしていきます。
service: myproject
provider:
name: aliyun
runtime: nodejs10
credentials: ~/.aliyuncli/credentials
stage: dev
region: ${env:ALIYUN_REGION}
plugins:
- serverless-aliyun-function-compute
functions:
dump:
handler: index.dump
events:
- http:
path: /dump
method: get
- oss:
sourceArn: acs:oss:${env:ALIYUN_REGION}:${env:ALIYUN_ACCOUNT_ID}:${env:OSS_BUCKET_NAME}
triggerConfig:
events:
- oss:ObjectCreated:*
今のところAPI GatewayトリガーとOSSトリガーのみサポートされているので他は手動で設定します。1
実践
API Gatewayトリガー
API Gatewayトリガーは当然リクエストの情報がイベントとして送信されます。
$ curl -s http://<api-gateway-id>-ap-northeast-1.alicloudapi.com/dump | jq
{
"body": "",
"headers": {
"X-Ca-Api-Gateway": "01234567-89AB-CDEF-0123-456789ABCDEF",
"X-Real-IP": "xxx.xxx.xxx.xxx",
"X-Forwarded-Proto": "http",
"X-Forwarded-For": "xxx.xxx.xxx.xxx",
"User-Agent": "curl/7.29.0",
"Accept": "*/*",
"CA-Host": "00112233445566778899aabbccddeeff-ap-northeast-1.alicloudapi.com"
},
"httpMethod": "GET",
"isBase64Encoded": true,
"path": "/dump",
"pathParameters": {},
"queryParameters": {}
}
OSSトリガー
testというファイルがあると思って読んでください。
aliyun oss cp test oss://<bucket-name>/test
出力されたイベントを整形したものが以下になります。
{
"events": [
{
"eventName": "ObjectCreated:PostObject",
"eventSource": "acs:oss",
"eventTime": "2019-12-13T07:58:49.000Z",
"eventVersion": "1.0",
"oss": {
"bucket": {
"arn": "acs:oss:ap-northeast-1:<account-id>:<bucket-name>",
"name": "<bucket-name>",
"ownerIdentity": "<owner-account-id>",
"virtualBucket": ""
},
"object": {
"deltaSize": 210,
"eTag": "00112233445566778899AABBCCDDEEFF",
"key": "test",
"size": 10
},
"ossSchemaVersion": "1.0",
"ruleId": "00112233445566778899aabbccddeeff01234567"
},
"region": "ap-northeast-1",
"requestParameters": {
"sourceIPAddress": "xxx.xxx.xxx.xxx"
},
"responseElements": {
"requestId": "00112233445566778899AABB"
},
"userIdentity": {
"principalId": "<principal-id>"
}
}
]
}
Log Serviceトリガー
出力されたイベントを整形したものが以下になります。ログの内容は届かないので改めてSDKで取得する必要があるようです。
{
"parameter": {
"source": {
"endpoint": "http://ap-northeast-1.log.aliyuncs.com"
},
"target": {
"endpoint": "http://ap-northeast-1.log.aliyuncs.com",
"logstoreName": "<log-store-name>",
"projectName": "<log-project-name>"
}
},
"source": {
"endpoint": "http://ap-northeast-1.log.aliyuncs.com",
"projectName": "<log-project-name>",
"logstoreName": "<log-store-name>",
"shardId": 0,
"beginCursor": "MTU3NjIyNjEzOTEyNTAwMjE2NA==",
"endCursor": "MTU3NjIyNjEzOTEyNTAwMjE2NQ=="
},
"jobName": "00112233445566778899aabbccddeeff01234567",
"taskId": "00112233-4455-6677-8899-aabbccddeeff",
"cursorTime": 1576228992
}
タイムトリガー
出力されたイベントを整形したものが以下になります。payload
はトリガーに設定した文字列がそのまま届きます。
{
"triggerTime": "2019-12-13T09:50:00Z",
"triggerName": "<trigger-name>",
"payload": "<paylod>"
}
CDNトリガー
出力されたイベントを整形したものが以下になります。CDNのイベントで何か処理をしたいというシチュエーションが想像できませんでした。
{
"events": [
{
"eventName": "CachedObjectsRefreshed",
"eventSource": "cdn",
"region": "cn-hangzhou",
"eventVersion": "1.0.0",
"eventTime": "2019-12-13T18:21:40+08:00",
"userIdentity": {
"aliUid": "<account-id>"
},
"eventParameter": {
"completeTime": 1576232499,
"createTime": 1576232492,
"domain": "cdn.example.com",
"objectPath": [
"/index.html"
],
"objectType": "File",
"taskId": 1234567890
},
"traceId": "00112233-4455-6677-8899-aabbccddeeff"
}
]
}
Table Storeトリガー
トリガーは発動したのですが何故かJSONではありませんでした。
どうやらTable StoreトリガーのイベントはCBORという形式らしいです。2
ちょっと調査が追いつかないので後回しにします。
\ufffdgVersiongSync-v1gRecords\ufffd\ufffdgColumns\ufffd\ufffdjColumnNamednameiTimestamp\u001b
MNSトリガー
出力されたイベントを整形したものが以下になります。
{
"TopicOwner": "<owner-account-id>",
"Message": "<message-payload>",
"Subscriber": "<subscriber-account-id>",
"PublishTime": 1576235089696,
"SubscriptionName": "<subscription-name>",
"MessageMD5": "00112233445566778899AABBCCDDEEFF",
"TopicName": "<topic-name>",
"MessageId": "00112233445566778899AABBCCDDEEFF"
}
HTTPトリガー
HTTPトリガーは他のトリガーと異なり関数の作成時にしか設定できません。また、呼び出される関数の引数も独特です。以下は関数作成時に生成されたソースコードから不要な箇所を取り除いたものですが、引数がどのようなものかは把握できるかと思われます。
var getRawBody = require('raw-body');
module.exports.handler = function(req, resp, context) {
console.log('hello world');
var params = {
path: req.path,
queries: req.queries,
headers: req.headers,
method : req.method,
requestURI : req.url,
clientIP : req.clientIP,
}
getRawBody(req, function(err, body) {
for (var key in req.queries) {
var value = req.queries[key];
resp.setHeader(key, value);
}
params.body = body.toString();
resp.send(JSON.stringify(params, null, ' '));
});
}
まとめ
AWS Lambdaと同様にさまざまなイベントを起点に関数を実行できるFunction Computeの各種イベントの形式を見てきました。いつかトリガーを利用する際に参照できるようにイベント形式を並べておきましたが、皆様の参考にもなれば幸いです。
余談
試す上で詰まったのがトリガーの権限でした。ロールを選択または作成するのですが、難しいことは考えずに「クイック承認」を使用するのが最も無難な選択だということに気づくまでに多くの時間がかかってしまいました。