【阿里云API】 阿里云API调用的若干说明
阿里云API
为了监控我们使用的一些阿里云产品,需要些一些脚本,定时调用这些脚本来获得相关阿里云产品的信息。
■ 概述
调用阿里云API大约分成两类方法,一个是直接从HTTP协议开始,自己根据阿里云的规则进行URL的编写然后发起请求,获得回应。这种方法比较繁琐(阿里云API的校验挺复杂的,昨天写了一晚上才成功写出对的URL)。另一种方法是利用阿里云提供的SDK(有多种语言的SDK,比如java,python,php等等),比如之前就有用过SDK来编写脚本监控RDS。下面从这两种方法来分别说明阿里云API的使用方法。
贴出阿里云官方API说明资料:
总体调用方式说明:【https://help.aliyun.com/document_detail/28616.html?spm=5176.doc51936.6.635.7Gl897】
资源监控接口说明:【https://help.aliyun.com/document_detail/51936.html?spm=5176.doc28616.6.637.6sm7b1】
预设监控项说明:【https://help.aliyun.com/document_detail/28619.html?spm=5176.doc51936.6.650.rpFTYc】
■ 用SDK调用API
其实对SDK的研究还没有很深入,基本上是对之前的人留下来的脚本的一个观摩分析,然后依葫芦画瓢。这里主要说明python的SDK。pythonSDK的使用手册【https://help.aliyun.com/document_detail/28622.html?spm=5176.doc28619.6.653.EIfwUD】
其实官网上说得也很清楚了。。
安装:
pip install aliyun-python-sdk-core
pip install aliyun-python-sdk-cms
安装完成之后,来看一下如何使用;
#!/usr/bin/env python
#coding=utf-8 from aliyunsdkcore import client #客户类,其实叫account感觉更加合理,因为它是维护accessKeyId和secretKeyId的对象
from aliyunsdkcms.request.v20170301 import QueryMetricListRequest #QueryMetricList是阿里云方面规定的一个名字,意思是要获取多条监控数据的请求
import json clt = client.AcsClient('access_key_id','secret_key_id','cn-hangzhou')
#构建客户对象时需要一明一暗两个KEY,然后第三个参数可以参见“调用方式”那个网页上上面的各个物理区域的代码,比如cn-hangzhou,cn-hongkong,us-west-1等等
request = QueryMetricListRequest.QueryMetricListRequest()
#===========================================================
#下面就是设置request中的各种参数,有可能没有涵盖所有的方法,不过也都大同小异,值得一提的是,可以看到所有参数都是字符串,即便是dimension本来是一个字典,
#period本来是一个数字,两个time本来是时间对象,都要转化成相关的字符串
#===========================================================
request.set_accept_format('JSON')
request.set_Project('acs_slb_dashboard')
request.set_Metric('ActiveConnection')
request.set_StartTime('2017-08-09 11:00:00')
request.set_EndTime('2017-08-09 11:10:00')
request.set_Dimensions(str({'instanceId':'instance_id','port':'port'}))
request.set_Period('') res = json.loads(clt.do_action_with_exception(request))
#选择with_exception的话出错是以raise Exception的形式报出的,否则就是返回的res是错误码和错误信息这样子。
print json.dumps(res,indent=4)
如果你是第一次接触阿里云API,很可能会觉得一脸懵逼。主要是针对各个参数的意义还不明确,对各个参数意义及格式规定的解说放在下面,直接用HTTP请求来调用API的章节里面。
■ 通过HTTP请求调用API
其实用SDK当然也是通过HTTP请求来调用的API,这里的通过HTTP请求是指没有任何包装的,纯粹用我们自己的代码从0开始建立起一个调用API的URL然后发出请求。
首先,阿里云似乎支持POST和GET两种HTTP方法的调用方式,但是我没有试过POST,现在官网上的说明文档好像也已经放弃POST了,所以之后的说明都是基于GET方法的。说到GET方法,我们的印象就是域名后面一长串带着各种百分号数字字母的URI(注意URL和URI的区别,URL是整串,URI是问号后面的一长串),那么阿里云API调用时的那串URI包含了哪些参数就是关键。
这些参数基本可以分成三个部分:
● 公共参数 每次请求都要包括的部分
公共参数在“调用方式”那张网页上有说明,包括
Format 要求返回的格式,默认是'xml',我们可以设置为'JSON'
Version 指当前API的版本,看官网要求,目前最新的是'2017-03-01'
AccessId 用户账号的明钥ID
SignatureMethod 签名使用的算法,目前是只有'HMAC-SHA1'一种选择,至于什么是签名下面会讲的
Timestamp 时间戳,使用的格式是'%Y-%m-%dT%XZ'(带T和Z的这个是ISO8601的标准时间格式),而且一定要用伦敦时区的时间,也就是说对于中国的使用者我们可以(( datatime.datetime.now - datetime.timedelta(hours=8)).strftime('%Y-%m-%dT%XZ'))
SignatureVersion 算法版本,目前写'1.0'即可
SignatureNonce 为了防止重放攻击设置的随机数,在python中可以用uuid来生成这个随机数: str(uuid.uuid1())
● 请求具体参数 跟这次请求想要获得的信息相关,每次请求之间都需要不同的参数
就监控而言,请求具体参数的说明在“查询监控数据”那张网页上。
Action 请求动作,请求监控数据就写QueryMetricList
Project 指明是监控什么产品,比如ECS就写'acs_ecs_dashboard',如果是SLB就写'acs_slb_dashboard',每个产品的这个字段信息可以在“预设监控项”的网页中看到
Metric 监控项名称,也是在“预设监控项”中查询
Period 时间间隔,以秒数计,说明返回的监控数据,两个时间点之间跨度多大。一般默认是60。
EndTime 指出查询的监控数据截止至什么时间
StartTime 指出查询的监控数据开始于什么时间,这两个时间参数可以写毫秒时间戳,也可以写成'%Y-%m-%d %X'的形式,推荐后者,因为python自带的时间戳生成time.time()是以秒为单位而非毫秒
Dimensions 用于过滤数据的k-v对对象,在python里的话可以str化一个字典来实现。Dimensions里面可以写哪些字段可以在“预设监控项”中查询,一般必然带有一个'instanceId'字段
Length 用于查询结果的分页,设置了Length之后最多只返回一定条数的结果
Cursor 游标
● 签名
Signature 签名,其实严格来说,签名是属于公共参数的一部分,只不过签名每次请求也是不同的,而且签名的生成要依靠上面两部分参数的信息。下面重点讲一下如何生成签名,感觉官网上讲得不是很清楚。。
● 签名生成方法
首先,签名是一串字符串,用于提供给阿里云后台校验我们的信息是否正确,有没有调出后台信息的权限。要生成这个签名,首先要把上面两个参数集合(在python中就是两个字典了)除了整合到一起,然后按照key的顺序对其排序,对排完序的每一对k-v对,分别将k和v都转化成url形式(python的话可以调用urllib.quote方法)的字符串,然后用等号连接这两个字符串得到一对k-v对的一个整体字符串。然后用'&'符号将各个k-v对的整体字符串按照之前排序(也就是k的顺序)连接起来,获得一个长的,包含了上面两个字典中所有键值对的字符串。
拿到这个长字符串之后,再用urllib.quote方法对其转义,此时可以看到比如冒号在结果的字符串中变成了%253A,这就是两次转义(: -> %3A -> %253A)的结果。根据官网上的说明我们对结果字符串还可以做一些转义上出现误差后的替换,比如replace('+','%20').replace('*', '%2A').replace('%7E', '~'),最终得到了一个更长的字符串。。
再在这个更长字符串的开头加上'GET&%2F&',这里注意两点,1.因为是GET方法所以这里写GET 2.这里的&和%不用再转义的,不要问为什么。。阿里云就是这么规定的。至此,我们得到了所谓的StringToSign,即用于签名的一个原料字符串。
接下来,要运用hmac-sha1的算法来对这个原料字符串进行散列取值,sha1算法还需要一个秘钥,这时候就是用户秘钥(secret_key_id)派上用场的时候,把secret_key_id的末尾加上一个'&',然后把其作为秘钥来进行计算,按照sha1的算法得到结果后再把它用base64的标准进行编码,编码完成之后去掉行尾的\n,就得到了最后的签名了。
下面给出python的实现代码:
string_to_sign = ''
for k, v in sorted(unsign_param.iteritems(), key=lambda x: x[0]):
string_to_sign += urllib.quote(k) + '=' + urllib.quote(v) + '&'
string_to_sign = 'GET&%2F&' + urllib.quote(string_to_sign[:-1]).replace('+', '%20').replace('*', '%2A').replace('%7E', '~')
# 要[:-1]的原因是因为生成string_to_sign的时候,最后必然会多出一个&,这个是不必要的。如果用的是'&'.join(xxx)这样的方法就没有这个烦恼了 import hashlib,hmac
coder = hmac.new(key=secret, msg=string_to_sign, digestmod=hashlib.sha1)
signature = coder.digest().encode('base64').strip() #记得encode出来行尾有换行符,要去掉
● 发出请求,接受回复
在做完签名之后,可以往之前没有Signature这个字段的公共参数字典里加上{'Signature':signature},然后整合公共参数字典和请求参数字典,得到了一个大字典,这个大字典就是我们在请求阿里云API时用到的所有参数了。把这个参数按照GET方法要求的样子整合到基本请求地址'http://metric.cn-hangzhou.aliyuncs.com/'(根据物理机房所在区域不同,基本地址也会有不同,参见“基本调用”那张网页)上面去,然后发出请求就可以了。
回复的数据如果成功,则是像下面这样的:
{
"Code": "200",
"Success": true,
"Period": "60",
"RequestId": "8AE2C5AD-7CB3-4B5D-BE21-72AD4F762D8E",
"Datapoints": [
{
"instanceId": "instance_id",
"timestamp": 1502263380000,
"Average": 280,
"userId": "xxxxxxxxxxxx",
"Maximum": 280,
"vip": "x.x.x.x",
"Minimum": 280,
"port": "443"
},
{
"instanceId": "instance_id",
"timestamp": 1502263440000,
"Average": 2024,
"userId": "xxxxxxxxxxxx",
"Maximum": 2024,
"vip": "x.x.x.x",
"Minimum": 2024,
"port": "443"
}
]
}
//数据已做脱敏处理
可以看到Datapoints字段下面的列表,其中每一项都是一个时间点上的监控数值的信息。
如果回复失败了,那么得到的可能会是下面这样的:
{
"Code": "SignatureDoesNotMatch",
"Message": "Specified signature is not matched with our calculation.",
"HostId": "metrics.cn-hangzhou.aliyuncs.com",
"RequestId": "B4086476-2299-45F5-AC99-00AC1769E4D5"
}
■ 完整的python请求实现
下面是一个较为完整的实现,用python写成,有些校验什么的主要是考虑到我们自己的业务场景, 可以不用管
#!/usr/bin/env python
# coding=utf-8
# @author:weiyz import sys
import os
import uuid
import datetime
import urllib
import hmac try:
import requests
except ImportError,e:
import urllib2 try:
import json
except ImportError,e:
import simplejson as json # 配置文件指定
ACCOUNT_CONF_FILE = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'xxxx.ini')
if not os.path.isfile(ACCOUNT_CONF_FILE):
raise Exception('Configuration file {0} is not found'.format(ACCOUNT_CONF_FILE)) try:
instance_id = sys.argv[1]
search_key = sys.argv[2]
account = sys.argv[3]
port = sys.argv[4]
search_type = sys.argv[5]
except IndexError, e:
raise Exception('Invalid arguments. Check there are four arguments for the script.') def get_key_from_account():
'''
通过读文件获得相关账号的AccessKeyId
:return:
'''
import ConfigParser
cf = ConfigParser.ConfigParser()
cf.read(ACCOUNT_CONF_FILE)
try:
return cf.get(account, 'id') , cf.get(account,'secret')
except ConfigParser.NoSectionError:
raise Exception('Account {0} is not configured in configuration.'.format(account)) def get_sign_param():
'''
进行公共参数字典、请求参数字典的汇总,并计算签名,最终把签名也加入字典当中
最终形成的就是完整的请求参数字典,只要整合成URI就可以发起请求了
:return:
'''
time_format = '%Y-%m-%dT%XZ'
time_stamp = (datetime.datetime.now() - datetime.timedelta(hours=8)).strftime(time_format)
access_key_id,secret = get_key_from_account()
unsign_public_param = {
'Format': 'JSON',
'Version': '2017-03-01',
'AccessKeyId': access_key_id,
'SignatureMethod': 'HMAC-SHA1',
'Timestamp': time_stamp, # 时间戳格式一定是带T和Z的那个
'SignatureVersion': '1.0',
'SignatureNonce': str(uuid.uuid1())
}
secret += '&'
req_param = {
'Action': 'QueryMetricList',
'Project': 'acs_slb_dashboard',
'Metric': search_key,
'Period': '',
'EndTime': datetime.datetime.now().strftime('%Y-%m-%d %X'),
'StartTime': (datetime.datetime.now() - datetime.timedelta(minutes=8)).strftime('%Y-%m-%d %X'),
'Dimensions': str({'instanceId': instance_id, 'port': port})
# 另外注意Dimensions这个字典里面的key也是要按照顺序排列的
} unsign_param = {}
unsign_param.update(unsign_public_param)
del (unsign_public_param)
unsign_param.update(req_param)
del (req_param)
string_to_sign = ''
for k, v in sorted(unsign_param.iteritems(), key=lambda x: x[0]):
string_to_sign += urllib.quote(k) + '=' + urllib.quote(v) + '&'
string_to_sign = 'GET&%2F&' + urllib.quote(string_to_sign[:-1]).replace('+', '%20').replace('*', '%2A').replace('%7E', '~') import hashlib
coder = hmac.new(key=secret, msg=string_to_sign, digestmod=hashlib.sha1)
signature = coder.digest().encode('base64').strip() unsign_param.update({'Signature': signature})
return unsign_param if __name__ == '__main__':
sign_param = get_sign_param()
base_url = 'http://metrics.cn-hangzhou.aliyuncs.com/' if 'requests' in locals():
res = requests.get(base_url, params=sign_param)
result = json.loads(res.content)
elif 'urllib2' in locals():
req = urllib2.Request(base_url+'?'+urllib.urlencode(sign_param))
res = urllib2.urlopen(req)
result = res.read()
json.loads(result)
else:
result = {'Message':'Sending Request Failed.'} if result.get('Code') != '' or result.get('Success') != True:
raise Exception('API Call Failed:[Error Message]{0}'.format(result.get('Message')))
def filter_result(result):
for datapoint in result.get('Datapoints'):
yield datapoint.get('Maximum'), datapoint.get('Average') maxlist, avglist = zip(*list(filter_result(result)))
max_, avg = max(maxlist), max(avglist) if search_type == 'max':
print max_
elif search_type == 'avg':
print avg
■ 其他一些注意点
● 调用监控数据是有时滞的
不知道其他产品的情况怎么样,今天我调用SLB的监控数据的话始终有7-8分钟的时滞。也就是说保持调取当前时间前8分钟之内的监控数据只能看到一条或两条数据,6分钟前开始那个节点到当前时间的监控数据是没有的。问了下阿里云的工作人员,发现这是他们内部的问题,不知道以后是否会修复。总之是这样的。
【阿里云API】 阿里云API调用的若干说明的更多相关文章
- 阿里云API网关(2)开放 API 并接入 API 网关
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- 阿里云人脸比对API封装
这是根据封装是根据阿里云官方给的Demo进行修改的,当时是因为编写微信小程序云函数需要使用到阿里云人脸比对接口,才对其进行封装的. 记录下来,方便下次使用. 复制下来可以直接使用. 用到的依赖如下: ...
- Java 使用阿里云短信的API接口
亲们上午好,写的不好的地方还望指正.谢谢各位! 引言 短信服务(Short Message Service)是阿里云为用户提供的一种通信服务的能力,支持快速发送短信验证码.短信通知等.(我这里只讲一个 ...
- 阿里云OSS 图片处理api(custom)
阿里云OSS 图片处理api(custom) 阿里云对象存储服务(Object Storage Service, 简称OSS) 学习了:https://blog.csdn.net/u014559227 ...
- 高德携手阿里云发布“LBS云”,账户打通只是第一步
位置.游戏.视频,是公认的基于云计算的三大移动端应用方向.而今,LBS云有了更多进展,在高价值应用与云平台之间实现了资源打通和融合,高德迈出了实质性的一步. 高德地图副总裁郄建军(左)与阿里云业务总经 ...
- ServerLess之云函数实践-天气API
关注我的个人博客,发掘更多的内容 ServerLess之云函数实践-天气API 前言 云计算是大势所趋 Serverless 架构即"⽆服务器"架构,它是一种全新的架构方式,是云计 ...
- web 直播&即时聊天------阿里云、融云
随着直播越来越火,所在公司也打算制作自己的直播,所以去了解了这方面,使用后发现还是有些问题需要记录的. 经过分析,制作直播应该是分为两块来做,即直播与实时评论.这里先去制作实时评论,等直播ok后,也会 ...
- web 直播&即时聊天------阿里云、融云(二)
上一篇简要主要介绍了融云制作聊天室的基本方法,这次基本属于对上一篇的补充以及进阶...^_^... (ps:吐槽一下,加了三个融云的线下qq群,全部没人解决问题,也不知道建此群的意义,若是民间的话就当 ...
- 揭秘!2周实现上云上市,阿里云SaaS上云工具包如何打造新云梯?
提到“上云”,很多人会理解成上IaaS,比如买一些计算.存储和网络云产品,把自己的应用系统部署上去.这的确是通常意义的上云.但对SaaS而言,需要从产品.商业.服务,三个维度考虑SaaS伙伴和客户的痛 ...
- 阿里云应用上边缘云解决方案助力互联网All in Cloud
九月末的杭州因为一场云栖大会变得格外火热. 9月25日,吸引全球目光的2019杭州云栖大会如期开幕.20000平米的展区集结数百家企业,为数万名开发者带来了一场前沿科技的饕餮盛宴. 如同往年一样,位于 ...
随机推荐
- R语言︱非结构化数据处理神器——rlist包
本文作者:任坤,厦门大学王亚南经济研究院金融硕士生,研究兴趣为计算统计和金融量化交易,pipeR,learnR,rlist等项目的作者. 近年来,非关系型数据逐渐获得了更广泛的关注和使用.下面分别列举 ...
- (三十)java多线程一
我们通常在电脑中打开的应用称作进程,一个应用就是一个进程,而一个进程里边一般包含多个线程. 系统要为每一个进程分配独立的内存空间,而进程里的多个线程共用这些内存. 我们通常所写的main方法就是一个线 ...
- java.sql.SQLException:ORA-01861:文字和格式字符串不匹配
1.错误描述 java.sql.SQLException:ORA-01861:文字和格式字符串不匹配 2.错误原因 字段名为statis_date在数据库中存储的数据类型是Date,而在Java中拼接 ...
- iOS - Quartz 2D 下载进度按钮绘制
1.绘制下载进度按钮 具体实现代码见 GitHub 源码 QExtension QProgressButton.h @interface QProgressButton : UIButton /// ...
- spring配置datasource三种方式及具体信息
1.使用org.springframework.jdbc.datasource.DriverManagerDataSource说明:DriverManagerDataSource建立连接是只要有连接就 ...
- freemarker中的left_pad和right_pad(十五)
freemarker中的left_pad和right_pad 1.简易说明 (1)left_pad 距左边 (2)right_pad 距右边 (3)当仅仅只有一个参数时,插入的是空白:当有两个参数时, ...
- freemarker中的if...elseif...else语句(七)
freemarker中的if...elseif...else语句 1.设计示例 <#if student.studentAge lt 12> ${student.studentName}不 ...
- C#图解教程 第六章 深入理解类
深入理解类 类成员成员修饰符的顺序实例类成员静态字段从类的外部访问静态成员 静态字段示例静态成员的生存期 静态函数成员其他静态类成员类型成员常量常量与静态量属性 属性声明和访问器属性示例使用属性属性和 ...
- html 点击复制
<span>集团登陆:</span> <input readonly id="jituan" type="text" value= ...
- Dubbo 新编程模型之外部化配置
外部化配置(External Configuration) 在Dubbo 注解驱动例子中,无论是服务提供方,还是服务消费方,均需要转配相关配置Bean: @Bean public Applicatio ...