高效查詢ECS可用資源的實踐

菠蘿先森發表於2018-02-23

摘要: 建立例項總碰到沒有資源,沒有許可權,產品限制等原因導致建立失敗,到底哪些資源是可以使用並建立成功的呢?針對這個問題,我們來說說如何高效查詢可用的資源列表。

  • 在某一地域有哪些可用區
  • 在某一可用區有哪些可用網路型別
  • 在某一可用區有哪些可用IO優化資源
  • 在某一可用區有哪些可用例項規格
  • 在某一可用區有哪些可用系統盤型別
  • 在某一可用區有哪些可用資料盤型別

您可以通過指定不同目標資源( DestinationResource )查詢不同型別的資源列表,再指定其他條件細化查詢。目標資源( DestinationResource) 的各個可選取值有不同的邏輯與(&&)要求。在下列順序列表中,排在越後面的引數其邏輯與(&&)苛刻程度越高。
順序:(Zone)> IoOptimized > InstanceType > SystemDisk > DataDisk
取值示例:

若引數 DestinationResource 取值為 InstanceType,則必須傳入引數 IoOptimized。
若引數 DestinationResource 取值為 SystemDisk,則必須傳入引數 IoOptimized 和 InstanceType。
若引數 DestinationResource 取值為 DataDisk,則必須傳入引數 IoOptimized、InstanceType 和 SystemDiskCategory。

除了您現在看到的這文章,您還可以前往API文件:

DescribeAvailableResource

aliyun-java-sdk-ecs版本在4.6.3及以上。


要點概述

sdk使用

    public DescribeAvailableResourceResponse doAction(DescribeAvailableResourceRequest describe) {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", product_accessKey, product_accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        try {
            DescribeAvailableResourceResponse response = client.getAcsResponse(describe);
            System.out.println(JSON.toJSONString(response));
            return response;

        } catch (ClientException e) {
            e.printStackTrace();
        }
        return null;
    }

查詢之前先確認所需資源的付費型別

image.png

查詢可用區資源

    public void doDescribeAvailableZones() {
        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("Zone");
        describe.setRegionId("cn-hangzhou");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        DescribeAvailableResourceResponse response = doAction(describe);
        if (null != response && CollectionUtils.isNotEmpty(response.getAvailableZones())) {
            List<AvailableZone> availableZones = response.getAvailableZones();
            List<String> list = new ArrayList<String>(availableZones.size());
            for (AvailableZone availableZone : availableZones) {
                if (availableZone.getStatus().equals("Available")) {
                    list.add(availableZone.getZoneId());
                }
            }
        }
    }

返回結果

{
    "availableZones": [
        {
            "availableResources": [],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-e"
        },
        {
            "availableResources": [],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-b"
        },
        {
            "availableResources": [],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-d"
        }
    ],
    "requestId": "0789B955-A173-4513-ADE4-80B7B4A4C921"
}

查詢可用網路型別資源

    public void doDescribeAvailableNetworks() {
        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("Network");
        describe.setRegionId("cn-hangzhou");
        //不傳就是查所有可用區
        describe.setZoneId("cn-hangzhou-e");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        doAction(describe);
    }

返回結果

{
    "availableZones": [
        {
            "availableResources": [
                {
                    "supportedResources": [
                        {
                            "status": "Available",
                            "value": "classic"
                        },
                        {
                            "status": "Available",
                            "value": "vpc"
                        }
                    ],
                    "type": "Network"
                }
            ],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-e"
        }
    ],
    "requestId": "7A56347F-8D2E-440A-884B-1EF66654C7A8"
}

查詢可用IO優化資源

沒有指定付費型別,InstanceChargeType預設就是PostPaid,SpotStrategy預設為NoSpot

    public void doDescribeAvailableIoOptimizeds() {
        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("IoOptimized");
        describe.setRegionId("cn-hangzhou");
        //不傳就是查所有可用區
        describe.setZoneId("cn-hangzhou-b");
        //不是必填值,根據自己需要的網路型別過濾更準確
        //describe.setNetworkCategory("Classic");
        doAction(describe);
    }

返回結果

{
    "availableZones": [
        {
            "availableResources": [
                {
                    "supportedResources": [
                        {
                            "status": "Available",
                            "value": "none"
                        },
                        {
                            "status": "Available",
                            "value": "optimized"
                        }
                    ],
                    "type": "IoOptimized"
                }
            ],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-b"
        }
    ],
    "requestId": "AA6CF750-E6D8-4696-BA0E-D3B7F66D127F"
}

image.png
過濾條件導致沒有可用資源時返回
image.png

查詢可用例項規格資源

若引數 DestinationResource 取值為 InstanceType,則必須傳入引數 IoOptimized

    public void doDescribeAvailableInstanceTypes() {
        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("InstanceType");
        describe.setRegionId("cn-hangzhou");
        //不傳就是查所有可用區
        describe.setZoneId("cn-hangzhou-d");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        //必填值 none:非 I/O 優化例項 ; optimized:I/O 優化例項
        describe.setIoOptimized("optimized");

        //不是必填值,根據自己需要的網路型別過濾更準確 Vpc:專有網路 ; Classic:經典網路
        describe.setNetworkCategory("Vpc");
        doAction(describe);
    }

返回結果 statusSoldOut為例項規格售罄

{
    "availableZones": [
        {
            "availableResources": [
                {
                    "supportedResources": [
                        {
                            "status": "Available",
                            "value": "ecs.gn4-c8g1.4xlarge"
                        },
                        {
                            "status": "Available",
                            "value": "ecs.gn4-c4g1.2xlarge"
                        },
                        {
                            "status": "Available",
                            "value": "ecs.gn4.8xlarge"
                        },
                        {
                            "status": "SoldOut",
                            "value": "ecs.gn4.14xlarge"
                        },
                        {
                            "status": "Available",
                            "value": "ecs.gn4-c4g1.xlarge"
                        },
                        {
                            "status": "Available",
                            "value": "ecs.gn4-c8g1.2xlarge"
                        }
                    ],
                    "type": "InstanceType"
                }
            ],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-d"
        }
    ],
    "requestId": "888B31FC-269B-4024-BFDA-263C57C67B31"
}

IoOptimized沒有傳入,則報錯:
Code: Invalid.Param
Message: The input parameter DestinationResource that is mandatory for processing this request is not supplied.

查詢可用系統盤資源

若引數 DestinationResource 取值為 SystemDisk,則必須傳入引數 IoOptimizedInstanceType

    public void doDescribeAvailableSystemDisks() {

        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("SystemDisk");
        describe.setRegionId("cn-hangzhou");
        //不傳就是查所有可用區
        describe.setZoneId("cn-hangzhou-d");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        //必填值 none:非 I/O 優化例項 ; optimized:I/O 優化例項
        describe.setIoOptimized("optimized");
        //必填值 例項規格
        describe.setInstanceType("ecs.gn4-c8g1.2xlarge");

        //不是必填值,根據自己需要的網路型別過濾更準確 Vpc:專有網路 ; Classic:經典網路
        describe.setNetworkCategory("Vpc");
        doAction(describe);

    }

返回結果

{
    "availableZones": [
        {
            "availableResources": [
                {
                    "supportedResources": [
                        {
                            "max": 500,
                            "min": 20,
                            "status": "Available",
                            "unit": "GB",
                            "value": "cloud_efficiency"
                        },
                        {
                            "max": 500,
                            "min": 20,
                            "status": "Available",
                            "unit": "GB",
                            "value": "cloud_ssd"
                        }
                    ],
                    "type": "SystemDisk"
                }
            ],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-d"
        }
    ],
    "requestId": "4063AA6A-01E1-46F0-9DB8-A74AF5FE98E6"
}

查詢可用資料盤資源

若引數 DestinationResource 取值為 DataDisk,則必須傳入引數 IoOptimizedInstanceTypeSystemDiskCategory
延用上面的程式碼

    public void doDescribeAvailableDataDisks() {

        DescribeAvailableResourceRequest describe = new DescribeAvailableResourceRequest();
        describe.setDestinationResource("DataDisk");
        describe.setRegionId("cn-hangzhou");
        //不傳就是查所有可用區
        describe.setZoneId("cn-hangzhou-d");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        //必填值 none:非 I/O 優化例項 ; optimized:I/O 優化例項
        describe.setIoOptimized("optimized");
        //必填值 例項規格
        describe.setInstanceType("ecs.gn4-c8g1.2xlarge");
        //必填值 系統盤型別
        describe.setSystemDiskCategory("cloud_ssd");

        //不是必填值,根據自己需要的網路型別過濾更準確 Vpc:專有網路 ; Classic:經典網路
        describe.setNetworkCategory("Vpc");
        doAction(describe);

    }

返回結果

{
    "availableZones": [
        {
            "availableResources": [
                {
                    "supportedResources": [
                        {
                            "max": 32768,
                            "min": 20,
                            "status": "Available",
                            "unit": "GB",
                            "value": "cloud_ssd"
                        },
                        {
                            "max": 2000,
                            "min": 5,
                            "status": "Available",
                            "unit": "GB",
                            "value": "cloud"
                        },
                        {
                            "max": 32768,
                            "min": 20,
                            "status": "Available",
                            "unit": "GB",
                            "value": "cloud_efficiency"
                        }
                    ],
                    "type": "DataDisk"
                }
            ],
            "regionId": "cn-hangzhou",
            "status": "Available",
            "zoneId": "cn-hangzhou-d"
        }
    ],
    "requestId": "8A43A1D2-0065-4050-AA40-C614FF94A336"
}

聯合查詢

     public final static String IOOPTIMIED = "IoOptimized";
    public final static String INSTANCETYPE = "InstanceType";
    public final static String SYSTEMDISK = "SystemDisk";
    public final static String DATADISK = "DataDisk";
    public final static String ZONE =  "Zone";
    public final static String NETWORK =  "Network";

    public DescribeAvailableResourceRequest doCommonRequest(DescribeAvailableResourceRequest describe) {
        if (null == describe) {
            describe = new DescribeAvailableResourceRequest();
        }
        describe.setRegionId("cn-hangzhou");
        // InstanceChargeType 預設為PostPaid
        // PrePaid:預付費,即 包年包月 ;
        // PostPaid:後付費,即 按量付費
        describe.setInstanceChargeType("PostPaid");
        // 當引數 InstanceChargeType 取值為 PostPaid 時,引數 SpotStrategy 才有效。
        // NoSpot:正常按量付費例項 ;
        // SpotWithPriceLimit:設定上限價格的競價例項 ;
        // SpotAsPriceGo:系統自動出價,最高按量付費價格
        describe.setSpotStrategy("NoSpot");
        return describe;
    }

    public List<String> getResources(String destinationResource, DescribeAvailableResourceRequest describe) {
        describe = doCommonRequest(describe);
        if(!ZONE.equals(destinationResource)) {
            List<String> zones =  getResources(ZONE,describe);
            //取所需的可用區,這裡取第一個值; 不傳就是查所有可用區
            describe.setZoneId(zones.get(0));
        }
        if(!ZONE.equals(destinationResource) && !NETWORK.equals(destinationResource)){
            List<String> networks =  getResources(NETWORK,describe);
            //不是必填值,根據自己需要的網路型別過濾更準確 Vpc:專有網路 ; Classic:經典網路
            describe.setNetworkCategory(networks.get(0));
        }
        if (INSTANCETYPE.equals(destinationResource)) {
            List<String> ioOpts = getResources(IOOPTIMIED, describe);
            //取所需的IO優化資源,這裡取第一個值
            describe.setIoOptimized(ioOpts.get(0));
        }
        if (SYSTEMDISK.equals(destinationResource)) {
            List<String> types = getResources(INSTANCETYPE, describe);
            //取所需的例項規格資源,這裡取第一個值
            describe.setInstanceType(types.get(0));
        }
        if (DATADISK.equals(destinationResource)) {
            List<String> systemDisks = getResources(SYSTEMDISK, describe);
            //取所需的系統盤資源,這裡取第一個值
            describe.setSystemDiskCategory(systemDisks.get(0));
        }
        describe.setDestinationResource(destinationResource);
        return getResponse(describe, destinationResource);
    }

    public List<String> getResponse(DescribeAvailableResourceRequest describe, String destinationResource) {
        DescribeAvailableResourceResponse response = doAction(describe);
        if (null != response && CollectionUtils.isNotEmpty(response.getAvailableZones())) {
            List<String> zones = new ArrayList<String>();
            for (AvailableZone availableZone : response.getAvailableZones()) {
                if(ZONE.equals(destinationResource)){
                    if (availableZone.getStatus().equals("Available")) {
                        zones.add(availableZone.getZoneId());
                    }
                }
                if (CollectionUtils.isNotEmpty(availableZone.getAvailableResources())) {
                    for (AvailableResource resource : availableZone.getAvailableResources()) {
                        if (resource.getType().equals(destinationResource)) {
                            if (CollectionUtils.isNotEmpty(resource.getSupportedResources())) {
                                List<String> types = new ArrayList<String>();
                                for (SupportedResource supportResource : resource.getSupportedResources()) {
                                    //只取可用資源,SoldOut為售罄
                                    if (supportResource.getStatus().equals("Available")) {
                                        types.add(supportResource.getValue());
                                    }
                                }
                                return types;
                            }
                        }
                    }
                }
            }
            if(CollectionUtils.isNotEmpty(zones)){
                return zones;
            }
        }
        return null;
    }

    //查詢所需目標型別資源的值
    public void doDescribeResources(String destinationResource) {
        List<String> values = getResources(destinationResource, null);
    }


相關文章