背景
目前阿里云的ECS实例规格已经达到大约300种,有17个region,分成Io优化和非Io优化,操作系统分为windows和非windows类型,网络类型分为vpc和classic,再加上价格单位 按小时、按周、按月、1年、2年、3年、4年、5年有不同力度的打折,如果笼统的计算,不同的组合方式达到了300 17 2 2 2 * 8=32万种,除去阿里云不支持的组合大概也有4万种有效组合方式,除此之外还有磁盘 带宽的价格。面对如此庞大的服务器组合方式,到底哪种组合方式既满足业务需求,又花最少的钱?用户可以到价格界面进行搜索,也可以下载价格JSON自行实现搜索脚本。
价格JSON结构解读
实例、磁盘、带宽价格
{
"currency": "CNY", //货币类型
"description": "", //价格组合key介绍,实例:RegionId::InstanceType::NetworkType::OSType::IoOptimized,磁盘:RegionId::DiskCategory::DiskType,带宽:RegionId
"disclaimer": "This pricing list is for informational purposes only.The actual price completely depends on ecs-buy.aliyun.com", //声明
"publicationDate": "2018-08-06T07:00:04Z", //价格JSON生成时间
"site": "CN", //站点
"type": "Instance", //资源类型
"version": "2.0.5", //版本
"pricingInfo": {
"ap-northeast-1::ecs.e4.2xlarge::vpc::linux::optimized": {
"hours": [ //价格单位,所有单位:hours weeks months years traffic
{
"period": "1", //数量
"price": "4.414" //价格
"unit": "GB", //实例:无此项,磁盘:磁盘存储大小单位,带宽:价格单位 1.hours 按量计费 2.months 包年包月计费,带宽大小上限单位unit=Mbps 3.traffic 按流量计费,流量单位unit=GB
"value": "1", //实例:无此项,磁盘和带宽:以unit为单位的个数。
}
]
}
}
}
各站点下载地址介绍
价格调整或有新规格上限,价格JSON版本会相继更新。
1.国内站,控制台界面
实例:https://g.alicdn.com/aliyun/ecs-price-info/2.0.5/price/download/instancePrice.json
磁盘:https://g.alicdn.com/aliyun/ecs-price-info/2.0.5/price/download/diskPrice.json
带宽:https://g.alicdn.com/aliyun/ecs-price-info/2.0.5/price/download/bandWidthPrice.json
2.国际站,控制台界面
实例:https://g.alicdn.com/aliyun/ecs-price-info-intl/2.0.3/price/download/instancePrice.json
磁盘:https://g.alicdn.com/aliyun/ecs-price-info-intl/2.0.3/price/download/diskPrice.json
带宽:https://g.alicdn.com/aliyun/ecs-price-info-intl/2.0.3/price/download/bandWidthPrice.json
3.日本站,控制台界面
实例:https://g.alicdn.com/aliyun/ecs-price-info-jp/2.0.1/price/download/instancePrice.json
磁盘:https://g.alicdn.com/aliyun/ecs-price-info-jp/2.0.1/price/download/diskPrice.json
带宽:https://g.alicdn.com/aliyun/ecs-price-info-jp/2.0.1/price/download/bandWidthPrice.json
搜索最低价格脚本示例
import urllib2
import json
from decimal import Decimal
# load price data
def load_url_price(url):
response = urllib2.urlopen(url)
priceStr = response.read()
priceJson = json.loads(priceStr)
return priceJson
# filtering according to conditions
def filter_by_condition(pricingInfo, regionId, instanceType, networkType, osType, ioType):
filterPricingInfo = {}
for key in pricingInfo:
if (regionId != None):
if (regionId not in key):
continue
if (instanceType != None):
if (instanceType not in key):
continue
if (networkType != None):
if (networkType not in key):
continue
if (osType != None):
if (osType not in key):
continue
if (ioType != None):
if (ioType not in key):
continue
filterPricingInfo[key] = pricingInfo[key]
return filterPricingInfo
# converted into monthly price
def get_month_price(priceItem, priceUnit):
price = Decimal(priceItem["price"])
period = Decimal(priceItem["period"])
if priceUnit == "hours":
return price * 24 * 30 / period
if priceUnit == "weeks":
return price / 7 * 30 / period
if priceUnit == "months":
return price / period
if priceUnit == "years":
return price / period / 12
# small item calculation
def get_min_price_item(result, priceItemList, period, priceUnit, pricingKey):
for priceItem in priceItemList:
if period == None or str(period) == str(priceItem["period"]):
monthPriceResult, monthPrice = 0, 0
if result != None:
monthPriceResult = get_month_price(result, result["priceUnit"])
monthPrice = get_month_price(priceItem, priceUnit)
if (monthPrice <= monthPriceResult or result == None):
result = priceItem
result["priceUnit"] = priceUnit
result["pricingKey"] = pricingKey
return result
# param validate
def param_validate(pricingInfo, regionId, instanceType, networkType, osType, ioType, priceUnit, period):
filterPricingInfo = filter_by_condition(pricingInfo, regionId, instanceType, networkType, osType, ioType)
checkMessageHeader = "Failed entry parameter check, "
if filterPricingInfo:
priceItem = filterPricingInfo.values()[0]
if priceUnit != None:
if not priceItem.has_key(priceUnit):
raise RuntimeError(
checkMessageHeader + "the priceUnit:{0} your input is not support.".format(priceUnit))
if period != None:
periodExisted = False
for tmpPriceUnit in priceItem:
for tmpPeriodItem in priceItem[tmpPriceUnit]:
checkPriceUnit = True if (priceUnit == None) else (tmpPriceUnit == priceUnit)
if str(tmpPeriodItem["period"]) == str(period) and checkPriceUnit:
periodExisted = True
break
if not periodExisted:
raise RuntimeError(
checkMessageHeader + "the priceUnit:{0} period:{1} your input is not support.".format(priceUnit,
period))
else:
raise RuntimeError(checkMessageHeader + "please check your regionId,instanceType,networkType,osType,ioType")
return filterPricingInfo
# query minimum price
def query_min_price(url, regionId, instanceType, networkType, osType, ioType, priceUnit, period):
result = None
priceJson = load_url_price(url)
pricingInfo = priceJson["pricingInfo"]
filterPricingInfo = param_validate(pricingInfo, regionId, instanceType, networkType, osType, ioType, priceUnit,
period)
for key in filterPricingInfo:
if priceUnit != None:
if filterPricingInfo[key].has_key(priceUnit):
result = get_min_price_item(result, filterPricingInfo[key][priceUnit], period, priceUnit, key)
else:
for priceUnitKey in filterPricingInfo[key]:
result = get_min_price_item(result, filterPricingInfo[key][priceUnitKey], period, priceUnitKey, key)
return result
if __name__ == '__main__':
url = "https://g.alicdn.com/aliyun/ecs-price-info/2.0.6/price/download/instancePrice.json"
regionId = None
instanceType = "ecs.g5.2xlarge"
# vpc classic
networkType = None
# linux windows
osType = None
# optimized none
ioType = None
# hours weeks months years
priceUnit = None
# 1-5
period = None
try:
print json.dumps(query_min_price(url, regionId, instanceType, networkType, osType, ioType, priceUnit, period))
except RuntimeError, e:
print e.message
小结
购买实例之前可以在价格界面搜索一下满足自己需求最低价格的实例类型,或者自行编写搜索脚本。这样您可以买到最实惠的机器,尽量为您节省成本。