本文介绍阿里云资源编排服务(ROS)(下面简称ROS)的异步通知功能。
创建、更新或删除资源栈(下面简称Stack)时,为了判断操作是否完成,通常我们会起一个定时任务,轮询Stack的状态直至完成。这种做法比较低效,使用异步通知功能,可以避免这个问题。ROS会在资源栈的操作完成时,回调通知客户。
使用方法
- 在创建Stack时,通过Webhook(2015-09-01版本)或NotificationURLs(2019-09-10版本)参数指定回调地址。
- 回调地址可以是一个或多个,最多5个。Webhook(2015-09-01版本)可以通过逗号分隔传递,NotificationURLs(2019-09-10版本)直接传递。
- 回调目前只支持HTTP POST。
- Stack至少包含一个输出。
示例
搭建HTTP服务器
申请一台拥有公网IP的ECS,并安全组入方向开放相应端口。这里我创建一台CentOS 7.6的机器,安全组开放8081端口。登录机器执行如下命令,启动一个Web服务。
pip install web.py==0.39
cat >website.py <<EOF
# -*- coding: utf-8 -*-
import web
import json
urls = (
'/', 'Index'
)
class Index(object):
def GET(self):
return "Hello, world!"
def POST(self):
s = web.data()
try:
print(json.dumps(json.loads(s), sort_keys=True, indent=4, separators=(',', ': ')))
except:
print(s)
return "Hello, world!"
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
EOF
python website.py 8081
创建Stack
以Python SDK为例,重点关注带注释部分。
# coding:utf-8
import json
import pprint
from aliyunsdkcore import client
from aliyunsdkros.request.v20150901 import CreateStacksRequest
AK = '<AK>' # Access Key
SECRET = '<SECRET>' # Access Key Secret
REGION = '<REGION>' # RegionId,比如cn-beijing
WEB_HOOK = 'http://<PUBLIC_IP>:8081' # 回调地址,使用ECS的公网IP代替PUBLIC_IP
class RequestHelper(object):
def __init__(self):
self._clt = client.AcsClient(AK, SECRET, REGION)
_instance = None
@classmethod
def instance(cls):
if not cls._instance:
cls._instance = cls()
return cls._instance
def run(self, request, body=None):
if body is not None:
request.set_content(json.dumps(body))
request.set_content_type('application/json')
status, headers, body = self._clt.get_response(request)
pprint.pprint(status)
pprint.pprint(headers)
try:
pprint.pprint(json.loads(body))
except ValueError:
pprint.pprint(body)
def main():
request = CreateStacksRequest.CreateStacksRequest()
body = {
'Name': 'test-web-hook',
'DisableRollback': False,
'TimeoutMins': 120,
'Webhook': WEB_HOOK, #通过Webhook参数指定回调地址
'Template': {
'ROSTemplateFormatVersion': '2015-09-01',
'Resources': {
'WaitConditionHandle': {
'Type': 'ALIYUN::ROS::WaitConditionHandle'
}
},
'Outputs': {
'CurlCli': {
'Value': {
'Fn::GetAtt': ['WaitConditionHandle', 'CurlCli']
}
}
}
}
}
RequestHelper.instance().run(request, body)
if __name__ == '__main__':
main()
观察回调结果
{
"Outputs": [
{
"Description": "No description given",
"OutputKey": "CurlCli",
"OutputValue": "curl -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'x-acs-region-id: cn-beijing' http://100.100.100.110/waitcondition?stackname=test-web-hook\\&stackid=80bd6b6c-e888-4573-ae3b-93d29144911d\\&resource=WaitConditionHandle\\&expire=1555424388\\&signature=e014516fa8028d8a8df9c9f4c9f7dc82a49421c1"
}
],
"StackId": "80bd6b6c-e888-4573-ae3b-93d29144911d",
"StackName": "test-web-hook",
"Status": "CREATE_COMPLETE"
}