All Products
Search
Document Center

Elastic Compute Service:Create a preemptible instance

Last Updated:Jul 31, 2023

This topic describes how to use Alibaba Cloud Elastic Compute Service (ECS) SDK for Java to call the DescribeAvailableResource operation to query available resources, call the DescribeSpotPriceHistory operation to query the historical prices of preemptible instances, and call the CreateInstance operation to create a preemptible instance.

Prerequisites

  • The version of Alibaba Cloud ECS SDK for Java is V4.2.0 or later.

  • The image that you want to use to create a preemptible instance contains all the environment dependencies that are required to run the instance. To ensure that a preemptible instance can process business data, we recommend that you use a custom image to create the instance. In this example, the image whose ID is m-bp146shijn7hujkui9*** is used.

  • The DescribeRegions operation is called to query the most recent list of regions in which ECS is activated. In this example, the region whose ID is cn-hangzhou is used.

  • The DescribeInstanceTypes operation is called to query the available instance types. In this example, the ecs.g5.large instance type is used.

Background information

Preemptible instances help you build cost-effective solutions to process business data. When you create a preemptible instance, you must specify a bidding mode to set a maximum hourly price and bid for an instance type. If your bid is greater than or equal to the market price and the instance type is well stocked, the preemptible instance is created and billed at the market price. Preemptible instances are used to control computing costs and are suitable for stateless applications. For more information, see Overview.

Procedure

  1. Encapsulate an ApiCaller.java class to initialize a profile and a client and add the exception handling logic.

    public class ApiCaller {
        IClientProfile profile;
        IAcsClient client;
    
        public ApiCaller() {
            // Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables are configured in the code runtime. 
            // If the project code is leaked, the AccessKey pair may be leaked and security issues may occur on all resources of your account. The following sample code obtains an AccessKey pair based on environment variables. We recommend that you use Security Token Service (STS). 
            profile = DefaultProfile.getProfile("cn-hangzhou", System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
            client = new DefaultAcsClient(profile);
        }
    
        public  <T extends AcsResponse> T doAction(AcsRequest<T> var1) {
            try {
                return  client.getAcsResponse(var1);
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                System.out.println("ErrCode:" + e.getErrCode());
                System.out.println("ErrMsg:" + e.getErrMsg());
                System.out.println("RequestId:" + e.getRequestId());
            }
            return null;
        }
     }
  2. Call the DescribeAvailableResource operation to query the instance types that are available in a specified region.

    public class DescribeAvailableResourceSample {
    
        public static void main(String[] args) {
    
            ApiCaller caller = new ApiCaller();
            DescribeAvailableResourceRequest request = new DescribeAvailableResourceRequest();
            // Call the DescribeRegionsRequest operation to obtain the region ID. 
            request.setRegionId("cn-hangzhou");
            request.setDestinationResource("InstanceType");
            // Required. Set the InstanceChargeType parameter to PostPaid. 
            request.setInstanceChargeType("PostPaid");
            // Required. Set the SpotStrategy parameter for the preemptible instance. 
            request.setSpotStrategy("SpotAsPriceGo");
            // Specify the zone in which to create the instance. If you do not specify a zone ID, all zones in which preemptible instances can be created are queried. 
            request.setZoneId("cn-hangzhou-h");
            // Specify an instance type. If you do not specify an instance type, all instance types that can be used to create preemptible instances are queried. 
            request.setInstanceType("ecs.g5.large");
            request.setSystemDiskCategory("cloud_ssd");
            request.setNetworkCategory("vpc");
    
            DescribeAvailableResourceResponse response = caller.doAction(request);
            System.out.println(JSON.toJSONString(response));
        }
    }

    Sample success response:

    {
        "RequestId": "D8491D5E-AB8A-4E22-BDB4-EEEE1F1C8241",
        "AvailableZones": {
            "AvailableZone": [
                {
                    "Status": "Available",
                    "RegionId": "cn-hangzhou",
                    "AvailableResources": {
                        "AvailableResource": [
                            {
                                "Type": "InstanceType",
                                "SupportedResources": {
                                    "SupportedResource": [
                                        {
                                            "Status": "Available",
                                            "Value": "ecs.g5.large",
                                            "StatusCategory": "WithStock"
                                        }
                                    ]
                                }
                            }
                        ]
                    },
                    "ZoneId": "cn-hangzhou-h",
                    "StatusCategory": "WithStock"
                }
            ]
        }
    }
  3. (Optional) Call the DescribeSpotPriceHistory operation to query the historical prices of preemptible instances.

    Note

    The DescribeSpotPriceHistory operation allows you to obtain the historical prices for up to the last 30 days.

    public class DescribeSpotPriceHistorySample {
    
        public static void main(String[] args) {
    
            ApiCaller caller = new ApiCaller();
            List<DescribeSpotPriceHistoryResponse.SpotPriceType> result = new ArrayList<DescribeSpotPriceHistoryResponse.SpotPriceType>();
            int offset = 0;
            while (true) {
                DescribeSpotPriceHistoryRequest request = new DescribeSpotPriceHistoryRequest();
                // Required. Specify a region ID. 
                request.setRegionId("cn-hangzhou");
                // Required. Specify a zone ID. 
                request.setZoneId("cn-hangzhou-b");
                // Required. Specify an instance type. 
                request.setInstanceType("ecs.g5.large");
                // Required. Specify a network type. 
                request.setNetworkType("vpc");
                // Optional. Specify the beginning of the time range to query. By default, the time range is 3 hours. 
                // request.setStartTime("2017-09-20T08:45:08Z");
                // Optional. Specify the end of the time range to query. If the end time is not specified, the current time is used as the end of the time range to query. 
                // request.setEndTime("2017-09-28T08:45:08Z");
                request.setOffset(offset);
                DescribeSpotPriceHistoryResponse response = caller.doAction(request);
                if (response != null && response.getSpotPrices() != null) {
                    result.addAll(response.getSpotPrices());
                }
                if (response.getNextOffset() == null || response.getNextOffset() == 0) {
                    break;
                } else {
                    offset = response.getNextOffset();
                }
            }
            if (!result.isEmpty()) {
                for (DescribeSpotPriceHistoryResponse.SpotPriceType spotPriceType : result) {
                    System.out.println(spotPriceType.getTimestamp() + "--->spotPrice:" + spotPriceType.getSpotPrice() + "---->originPrice:" + spotPriceType.getOriginPrice());
                }
                System.out.println(result.size());
            } else {
            }
    
        }
    
    }

    Sample success response:

    2017-09-26T06:28:55Z--->spotPrice:0.24---->originPrice:1.2
    2017-09-26T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
    2017-09-26T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
    2017-09-27T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
    2017-09-27T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
    2017-09-28T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
    2017-09-28T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
    2017-09-29T06:28:55Z--->spotPrice:0.24---->originPrice:1.2
  4. Call the CreateInstance operation to create a preemptible instance.

    To create multiple preemptible instances at a time, you can call the RunInstances operation. For more information, see Batch create ECS instances.

    public class CreateInstanceSample {
    
        public static void main(String[] args) {
    
            ApiCaller caller = new ApiCaller();
    
            CreateInstanceRequest request = new CreateInstanceRequest();
            // Specify a region ID. 
            request.setRegionId("cn-hangzhou");
            // Specify a zone ID. 
            request.setZoneId("cn-hangzhou-h"); 
            // Specify the ID of a security group. 
            request.setSecurityGroupId("sg-bp11nhf94ivkdxwb2***");
            // Specify an image ID. We recommend that you use a custom image to create a preemptible instance. 
            request.setImageId("m-bp146shijn7hujkui9***");
            // Specify the ID of a vSwitch that resides in the same virtual private cloud (VPC) as the specified security group. 
            request.setVSwitchId("vsw-bp164cyonthfudn9kj***");
    
            // Specify an instance type. 
            request.setInstanceType("ecs.g5.large"); 
    
            // Specify the category of the system disk. Valid values: cloud_essd, cloud_ssd, cloud_efficiency, and cloud. 
            request.setSystemDiskCategory("cloud_ssd");
            request.setSystemDiskSize(40);
    
            // Required. Set the InstanceChargeType parameter to PostPaid. 
            request.setInstanceChargeType("PostPaid");
            // Set the SpotStrategy parameter to SpotWithPriceLimit. You can also set the SpotStrategy parameter to SpotAsPriceGo to use the system-provided price as the bid price, which can be up to the pay-as-you-go price. In this case, you do not need to specify the SpotPriceLimit parameter. 
            request.setSpotStrategy("SpotWithPriceLimit");
            // If you set the SpotStrategy parameter to SpotWithPriceLimit, the bid price that you specify must be higher than the market price at the time of purchase. Otherwise, the instance cannot be created. 
            request.setSpotPriceLimit(0.25F);
    
            // Set the Amount parameter to 2 to create two preemptible instances. By default, only one preemptible instance is created if this parameter is not set. 
            // request.setAmount(2);
    
            CreateInstanceResponse response = caller.doAction(request);
            System.out.println(response.getInstanceId());
    
        }
    }
  5. Query the recycle time of the preemptible instance.

    Important

    Preemptible instances can be recycled. To prevent business from being affected by the release of preemptible instances, we recommend that you set up a service interruption mechanism or a load balancing mechanism when you create preemptible instances.

    • Method 1: Run the following command in the operating system of the preemptible instance to query the recycle time of the instance based on the instance metadata:

      curl http://100.100.100.200/latest/meta-data/instance/spot/termination-time
      Note

      If the command output is empty, you can continue to use the preemptible instance. If the command output contains a point in time that follows the format of yyyy-MM-ddTHH:mm:ssZ and is displayed in UTC, the preemptible instance will be recycled at that point in time. Example: 2023-07-05T18:02:00Z.

    • Method 2: Call the DescribeInstances operation to check whether the instance is in the To Be Released state based on the OperationLocks array in the response.

      public class DescribeInstancesSample {
        public static void main(String[] args) throws InterruptedException {
      
            ApiCaller caller = new ApiCaller();
            JSONArray allInstances = new JSONArray();
            allInstances.addAll(Arrays.asList("i-bp18hgfai8ekoqwo0***", "i-bp1ecbyds24ij63w1***"));
      
            while (!allInstances.isEmpty()) {
      
                DescribeInstancesRequest request = new DescribeInstancesRequest();
                request.setRegionId("cn-hangzhou");
                // Specify an instance ID to make the query more efficient. 
                request.setInstanceIds(allInstances.toJSONString());
                DescribeInstancesResponse response = caller.doAction(request);
                List<DescribeInstancesResponse.Instance> instanceList = response.getInstances();
      
                if (instanceList != null && !instanceList.isEmpty()) {
                    for (DescribeInstancesResponse.Instance instance : instanceList) {
                        System.out.println("result:instance:" + instance.getInstanceId() + ",was created in zone:" + instance.getZoneId());
                        if (instance.getOperationLocks() != null) {
                            for (DescribeInstancesResponse.Instance.LockReason lockReason : instance.getOperationLocks()) {
                                System.out.println("instance: " + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",instanceStatus:" + instance.getStatus());
                                if ("Recycling".equals(lockReason.getLockReason())) {
                                    // Obtain the recycle time of the instance. The IDs of recycled instances are deleted from the instance ID list. 
                                    System.out.println("Preemptible instance will be recycled immediately, instance id: " + instance.getInstanceId());
                                    allInstances.remove(instance.getInstanceId());
                                }
                            }
                        }
                    }
                    System.out.print("Try describeInstancesRequest again later...");
                    Thread.sleep(2 * 60 * 1000);
                } else {
                    break;
                }
            }
        }
      }

      If the following response is returned, the preemptible instance is in the To Be Released state:

      instance: i-bp1ecbyds24ij63w1***-->lockReason:Recycling,instanceStatus:Stopped
      Preemptible instance will be recycled immediately, instance id: i-bp1ecbyds24ij63w1***
    • Method 3: Call the DescribeSystemEventAttribute operation of CloudMonitor to query the recycle time of the preemptible instance.

      public class DescribeSystemEventAttribute {
      
        public static void main(String[] args) {
              // Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables are configured in the code runtime. 
              // If the project code is leaked, the AccessKey pair may be leaked and security issues may occur on all resources of your account. The following sample code obtains an AccessKey pair based on environment variables. We recommend that you use STS. 
          DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
          IAcsClient client = new DefaultAcsClient(profile);
      
          DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest();
          // Specify a region ID. 
          request.setRegionId("cn-hangzhou");
          // Specify an Alibaba Cloud service. 
          request.setProduct("ecs");
          // Specify the beginning of the time range to query. 
          request.setStartTime("1574064240000");
      
          try {
            DescribeSystemEventAttributeResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
          } catch (ServerException e) {
            e.printStackTrace();
          } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
          }
      
        }
      }

      If the following response is returned, the preemptible instance is in the To Be Released state:

      {
       "SystemEvents": {
        "SystemEvent": [
         {
          "Name": "Instance:PreemptibleInstanceInterruption",
          "Status": "Normal",
          "Time": 1574064244000,
          "Product": "ECS",
          "ResourceId": "acs:ecs:cn-hangzhou:133160284996****:instance/i-bp19w6o2tqa9jvoh8***",
          "RegionId": "cn-hangzhou",
          "Level": "WARN",
          "Content": "{\"action\":\"delete\",\"instanceId\":\"i-bp19w6o2tqa9jvoh8***\"}",
          "GroupId": "0",
          "InstanceName": "i-bp19w6o2tqa9jvoh8***"
         }
        ]
       },
       "Message": "200",
       "RequestId": "D4730844-EF73-4856-BFF3-1BDAE8E54C81",
       "Success": true,
       "Code": "200"
      }

References