开发者社区> CodeSample> 正文

感知SPOT实例中断事件并创建镜像实例

简介: 本示例介绍如何使用Alibaba Cloud SDK for Java在spot实例释放前创建自定义镜像。

背景信息

您在使用抢占式实例时,实例会因为库存或价格的波动而中断实例,中断后数据无法恢复。我们可以采用感知抢占式实例中断事件自动创建镜像,然后使用创建出的镜像来创建实例,防止实例中断而导致的数据丢失。

工作流程图

工作流程如下图所示。

工作流程图

前提条件

在使用本教程之前,请确保已完成以下操作:

  • 请在阿里云控制台中的AccessKey管理页面查看您的访问密钥。您只有获取了阿里云账号和访问密钥(AccessKey),才可以使用Alibaba Cloud SDK for Java。

  • 确保您已经安装了Alibaba Cloud SDK for Java,准确的SDK版本号,请参见阿里云开发工具包(SDK)

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>java.demo</groupId>
        <artifactId>test</artifactId>
        <version>1.0-SNAPSHOT</version>
        <dependencies>
           <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.68</version>
            </dependency>
    
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-ecs</artifactId>
                <version>4.23.10</version>
            </dependency>
    
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-core</artifactId>
                <version>4.0.8</version>
            </dependency>
        </dependencies>
    </project>

示例代码

本文操作示例主要以代码形式体现,具体代码如下:

  1. 创建抢占式实例。

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.IAcsClient;
    import com.aliyuncs.ecs.model.v20140526.RunInstancesRequest;
    import com.aliyuncs.ecs.model.v20140526.RunInstancesResponse;
    import com.aliyuncs.profile.DefaultProfile;
    
    /**
     * 通过RunInstances创建抢占式实例。
     */
    public class CreateSpotInstance {
    
        static IAcsClient client;
        /**
         * 请将regionId修改为您实例的地域ID。
         */
        static String regionId = "cn-shanghai";
        /**
         * 请将zoneId修改为您实例的可用区ID。
         */
        static String zoneId = "cn-shanghai-l";
        /**
         * 请将InstanceType修改为您需要的实例规格。
         */
        static String instanceType = "ecs.s6-c1m1.small";
        /**
         * 请将imagesId修改为您需要的镜像ID。
         */
        static String imagesId = "centos_7_06_64_20G_alibase_20190711.vhd";
        /**
         * 请将vSwitchId修改为您的交换机ID。
         */
        static String vSwitchId = "<your-vsw-id>";
        /**
         * 请将securityGroupId修改为您的安全组ID。
         */
        static String securityGroupId = "<your-sg-id>";
        /**
         * 请将spotStrategy修改为您想选择的抢占策略。
         */
        static String spotStrategy = "SpotAsPriceGo";
        /**
         * 请将spotDuration修改为您想使用的时长,如果您不确定时长,可以设置为0。
         */
        static Integer spotDuration = 0;
        /**
         * 请将password修改为您的密码。
         */
        static String password = "<your-passwd>";
    
        public static void main(String[] args) {
            client = Initialization();
            createInstance();
        }
    
        private static IAcsClient Initialization() {
            // 初始化请求参数。
            DefaultProfile profile = DefaultProfile.getProfile(
                    regionId,    // 您的实例所在地域ID。
                    "<your-access-key-id>",   // 您的AccessKey ID。
                    "<your-access-key-secret>");  // 您的AccessKey Secret。
            return new DefaultAcsClient(profile);
        }
    
        //创建实例。
        public static String createInstance() {
            try {
                RunInstancesRequest request = new RunInstancesRequest();
                request.setRegionId(regionId);
                request.setZoneId(zoneId);
                request.setInstanceType(instanceType);
                request.setSpotDuration(spotDuration);
                request.setSpotStrategy(spotStrategy);
                request.setImageId(imagesId);
                request.setVSwitchId(vSwitchId);
                request.setSecurityGroupId(securityGroupId);
                request.setInstanceChargeType("PostPaid");
                request.setPassword(password);
                request.setInternetMaxBandwidthOut(1);
                RunInstancesResponse response = client.getAcsResponse(request);
                if (null == response.getInstanceIdSets() || response.getInstanceIdSets().isEmpty()) {
                    return null;
                }
                String instanceId = response.getInstanceIdSets().get(0);
                System.out.println("创建的实例ID: " + instanceId);
                return instanceId;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
  2. 感知SPOT实例中断事件, 并自动创建自定义镜像。

    import com.alibaba.fastjson.JSON;
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.IAcsClient;
    import com.aliyuncs.ecs.model.v20140526.*;
    import com.aliyuncs.profile.DefaultProfile;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     *感知SPOT实例中断事件, 并自动创建自定义镜像。
     *
     *通过DescribeInstances查询实例信息。
     *
     *通过CreateImage 创建自定义镜像。
     */
    public class CreateSpotImage {
        static IAcsClient client;
        /**
         * 请将regionNo修改为您实例的地域ID。
         */
        static String regionId = "cn-shanghai";
        /**
         * 请将instanceId修改为您的实例ID。
         */
        static String instanceId = "<your-instance-id>";
    
        public static void main(String[] args) {
            client = Initialization();
            // 1. 等待实例到待回收状态。
            waitForInstanceMarked();
            System.out.println("spot instance will be recycled immediately, instance id:" + instanceId);
            // 2. 实例被标记为待回收之后,创建镜像,以便后续恢复。
            String image1 = createImage();
            waitCreateImageSuccess(image1);
        }
    
        public static void waitForInstanceMarked() {
            ArrayList<String> instanceIds = new ArrayList<>();
            instanceIds.add(instanceId);
            String instanceIdStr = JSON.toJSONString(instanceIds);
    
            boolean isMarked = false;
            // 判断实例是否被标记为待回收。
            while (!isMarked) {
                try {
                    DescribeInstancesRequest request = new DescribeInstancesRequest();
                    // 指定实例所在的地域。
                    request.setRegionId(regionId);
                    // 指定实例ID,提高查询效率。
                    request.setInstanceIds(instanceIdStr);
                    // 接收响应结果。
                    DescribeInstancesResponse response = client.getAcsResponse(request);
                    // 获取实例相关的返回结果。
                    List<DescribeInstancesResponse.Instance> instanceList = response.getInstances();
                    if (instanceList == null || instanceList.isEmpty()) {
                        break;
                    }
                    DescribeInstancesResponse.Instance instance = instanceList.get(0);
                    // 输出被查询的实例ID与可用区信息。
                    if (instance.getOperationLocks() == null) {
                        continue;
                    }
                    for (DescribeInstancesResponse.Instance.LockReason lockReason : instance.getOperationLocks()) {
                        // 如果实例被锁定,输出指定实例ID以及对应的锁定类型。
                        System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
                        if ("Recycling".equals(lockReason.getLockReason())) {
                            isMarked = true;
                        }
                    }
                    Thread.sleep(2 * 1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static String createImage() {
            try {
                CreateImageRequest request = new CreateImageRequest();
                request.setRegionId(regionId);
                request.setInstanceId(instanceId);
                CreateImageResponse response = client.getAcsResponse(request);
                System.out.println(response.getImageId());
                return response.getImageId();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static void waitCreateImageSuccess(String imageId) {
    
            boolean isSuccess = false;
            while (!isSuccess) {
                DescribeImagesResponse.Image image = describeImage(imageId);
                if (null == image) {
                    System.err.println("image not exist. imageId: " + imageId);
                    break;
                }
                if ("Available".equals(image.getStatus())) {
                    isSuccess = true;
                }
            }
        }
    
        public static DescribeImagesResponse.Image describeImage(String imageId) {
            try {
                Thread.sleep(6 * 60 * 1000 );
                DescribeImagesRequest imagesRequest = new DescribeImagesRequest();
                imagesRequest.setRegionId(regionId);
                imagesRequest.setImageId(imageId);
                imagesRequest.setPageSize(100);
                DescribeImagesResponse imagesResponse = client.getAcsResponse(imagesRequest);
                if (null == imagesResponse.getImages() || imagesResponse.getImages().isEmpty()) {
                    return null;
                }
                return imagesResponse.getImages().get(0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        private static IAcsClient Initialization() {
            // 初始化请求参数。
            DefaultProfile profile = DefaultProfile.getProfile(
                    regionId,    // 您的实例所在地域ID。
                    "<your-access-key-id>",   // 您的AccessKey ID。
                    "<your-access-key-secret>");  // 您的AccessKey Secret。
            return new DefaultAcsClient(profile);
        }
    
    }
  3. 创建使用自定义镜像的抢占式实例,将imageId替换成第二步中创建的imageId。

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.IAcsClient;
    import com.aliyuncs.ecs.model.v20140526.RunInstancesRequest;
    import com.aliyuncs.ecs.model.v20140526.RunInstancesResponse;
    import com.aliyuncs.profile.DefaultProfile;
    
    /**
     *通过RunInstances创建抢占式实例。
     */
    public class CreateSpotInstanceFromImage {
    
        static IAcsClient client;
        /**
         * 请将regionNo修改为您实例的地域ID。
         */
        static String regionId = "cn-shanghai";
        /**
         * 请将zoneId修改为您实例的可用区ID。
         */
        static String zoneId = "cn-shanghai-l";
        /**
         * 请将InstanceType修改为您需要的实例规格。
         */
        static String instanceType = "ecs.s6-c1m1.small";
        /**
         * 将此imageId改成上一步自定义生成的imageId。
         */
        static String imagesId = "<your-image-id>";
        /**
         * 请将vSwitchId修改为您的交换机ID。
         */
        static String vSwitchId = "<your-vsw-id>";
        /**
         * 请将securityGroupId修改为您的安全组ID。
         */
        static String securityGroupId = "<your-sg-id>";
        /**
         * 请将spotStrategy修改为您想选择的抢占策略。
         */
        static String spotStrategy = "SpotAsPriceGo";
        /**
         * 请将spotDuration修改为您想使用的时长,如果您不确定时长,可以设置为0。
         */
        static Integer spotDuration = 0;
        /**
         * 请将password修改为您的密码。
         */
        static String password = "<your-passwd>";
    
        public static void main(String[] args) {
            client = Initialization();
            createInstance();
        }
    
        private static IAcsClient Initialization() {
            // 初始化请求参数。
            DefaultProfile profile = DefaultProfile.getProfile(
                    regionId,    // 您的实例所在地域ID。
                    "<your-access-key-id>",   // 您的AccessKey ID。
                    "<your-access-key-secret>");  // 您的AccessKey Secret。
            return new DefaultAcsClient(profile);
        }
    
        //创建实例。
        public static String createInstance() {
            try {
                RunInstancesRequest request = new RunInstancesRequest();
                request.setRegionId(regionId);
                request.setZoneId(zoneId);
                request.setInstanceType(instanceType);
                request.setSpotDuration(spotDuration);
                request.setSpotStrategy(spotStrategy);
                request.setImageId(imagesId);
                request.setVSwitchId(vSwitchId);
                request.setSecurityGroupId(securityGroupId);
                request.setInstanceChargeType("PostPaid");
                request.setPassword(password);
                request.setInternetMaxBandwidthOut(1);
                RunInstancesResponse response = client.getAcsResponse(request);
                if (null == response.getInstanceIdSets() || response.getInstanceIdSets().isEmpty()) {
                    return null;
                }
                String instanceId = response.getInstanceIdSets().get(0);
                System.out.println("创建的实例ID: " + instanceId);
                return instanceId;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

相关链接

分享:
若有任何问题或疑惑,请反馈给我们 立即提问

做技术先进、性能优异、稳如磐石的弹性计算!

官方博客
最新文章
用户活动