逐渐理解open api的意义,试了下阿里云的续费接口,续费一个月
package com.test; /** * @author * @date 2018/12/05 */ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.aliyuncs.AcsRequest; import com.aliyuncs.AcsResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.ecs.model.v20140526.DescribeInstancesRequest; import com.aliyuncs.ecs.model.v20140526.DescribeInstancesResponse; import com.aliyuncs.ecs.model.v20140526.RenewInstanceRequest; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class AliyunRenewInstancesExample { private String accessKeyId = "your-accessKeyId"; private String accessSecret = "your-accessSecret"; /** * 实例所属的地域ID */ private String regionId = "cn-beijing"; /** * 指定的需要续费的实例 ID */ private String[] instanceIds = new String[] {"i-m************"}; /** * 预付费续费时长 */ private Integer period = 1; /** * 续费时长单位,取值:Week/Month */ private String periodUnit = "Month"; private Map<String, InstanceExpiredModel> instanceExpiredModelMap = new HashMap<String, InstanceExpiredModel>(); private static final ExecutorService RENEW_INSTANCE_POOL = Executors.newFixedThreadPool(500); private static final Integer CHECK_EXPIRED_TIME_OUT_MILLISECOND = 60 * 1000; private static final Integer CHECK_EXPIRED_TIME_INTERVAL_MILLISECOND = 2 * 1000; private static final String INSTANCE_CHARGE_TYPE_PREPAID = "PrePaid"; private static final String DESCRIBE_INSTANCES_FILTER_KEY_EXPIRED_START_TIME = "ExpiredStartTime"; private static final String DESCRIBE_INSTANCES_FILTER_KEY_EXPIRED_END_TIME = "ExpiredEndTime"; public static void main(String[] args) { /** * 使用须知: * 调用 OpenAPI 续费会自动扣费,请谨慎调用 * 您的账号必须支持账号余额支付或信用支付,请确保金额充足 * * 调用续费API后会对 新的到期时间 和 原始的到期时间 进行比较并分别输出成功和失败的实例 */ new AliyunRenewInstancesExample().callRenewInstance(); } private void callRenewInstance() { /** * 若需查询需要续费的实例,可查看 describeNeedRenewInstances 方法 */ //List<String> needRenewInstanceIds = describeNeedRenewInstances(); List<String> instanceIdList = Arrays.asList(instanceIds); List<DescribeInstancesResponse.Instance> instances = describeInstances(instanceIdList); if (!checkInstanceIds(instances, instanceIdList)) { return; } updateInstanceOriginalExpiredTime(instances); for (final String instanceId : instanceIdList) { RENEW_INSTANCE_POOL.execute(new Runnable() { public void run() { RenewInstanceRequest request = new RenewInstanceRequest(); request.setRegionId(regionId); request.setInstanceId(instanceId); request.setPeriod(period); request.setPeriodUnit(periodUnit); callOpenApi(request, instanceExpiredModelMap.get(instanceId)); } }); } try { RENEW_INSTANCE_POOL.shutdown(); RENEW_INSTANCE_POOL.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { e.printStackTrace(); } checkInstancesExpiredTime(instanceIdList); } /** * 每2秒中检查一次实例的到期时间,超时时间设为1分钟 * * @param instanceIds 需要检查的实例ID */ private void checkInstancesExpiredTime(List<String> instanceIds) { Long startTime = System.currentTimeMillis(); for (;;) { boolean allCompleted = true; Long timeStamp = System.currentTimeMillis(); updateInstanceNewExpiredTime(instanceIds); for (String instanceId : instanceExpiredModelMap.keySet()) { InstanceExpiredModel instanceExpiredModel = instanceExpiredModelMap.get(instanceId); if (instanceExpiredModel.newExpiredTime == null && instanceExpiredModel.errorCode == null) { allCompleted = false; } } if (allCompleted) { logRenewResult(); return; } if (timeStamp - startTime > CHECK_EXPIRED_TIME_OUT_MILLISECOND) { logInfo(String.format("Check instance new expiredTime timeout. Because it takes too much time, View the result detail: %s", JSON.toJSONString(instanceExpiredModelMap, SerializerFeature.PrettyFormat))); return; } sleepSomeTime(CHECK_EXPIRED_TIME_INTERVAL_MILLISECOND); } } private boolean checkInstanceIds(List<DescribeInstancesResponse.Instance> instances, List<String> instanceIds) { if (instances.size() != instanceIds.size()) { List<String> responseInstanceIds = new ArrayList<String>(); List<String> invalidInstanceIds = new ArrayList<String>(); for (DescribeInstancesResponse.Instance instance : instances) { responseInstanceIds.add(instance.getInstanceId()); } for (String instanceId : instanceIds) { if (!responseInstanceIds.contains(instanceId)) { invalidInstanceIds.add(instanceId); } } logInfo(String.format("Fail. CheckInstanceIds failure. Invalid InstanceIds: %s", JSON.toJSONString(invalidInstanceIds))); return false; } return true; } /** * 记录 instance 原始到期时间,以便在调用续费 OpenAPI 后 check 到期时间是否发生变化来判断续费是否成功 * * @param instances * @return */ private boolean updateInstanceOriginalExpiredTime(List<DescribeInstancesResponse.Instance> instances) { for (DescribeInstancesResponse.Instance instance : instances) { InstanceExpiredModel instanceExpiredModel = new InstanceExpiredModel(); instanceExpiredModel.instanceId = instance.getInstanceId(); instanceExpiredModel.originalExpiredTime = instance.getExpiredTime(); instanceExpiredModelMap.put(instance.getInstanceId(), instanceExpiredModel); } return true; } private void updateInstanceNewExpiredTime(List<String> instanceIds) { List<DescribeInstancesResponse.Instance> instances = describeInstances(instanceIds); for (DescribeInstancesResponse.Instance instance : instances) { InstanceExpiredModel instanceExpiredModel = instanceExpiredModelMap.get(instance .getInstanceId()); if (!instance.getExpiredTime().equals(instanceExpiredModel.originalExpiredTime)) { instanceExpiredModel.newExpiredTime = instance.getExpiredTime(); } } } private List<DescribeInstancesResponse.Instance> describeInstances(List<String> instanceIds) { int offset = 0; int pageSize = 100; int totalCount = instanceIds.size(); List<DescribeInstancesResponse.Instance> instances = new ArrayList<DescribeInstancesResponse.Instance>(); while (offset < totalCount) { DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest(); describeInstancesRequest.setRegionId(regionId); describeInstancesRequest.setPageSize(pageSize); describeInstancesRequest.setInstanceChargeType(INSTANCE_CHARGE_TYPE_PREPAID); describeInstancesRequest.setInstanceIds(JSON.toJSONString(instanceIds.subList(offset, Math.min(totalCount, offset + pageSize)))); DescribeInstancesResponse response = callOpenApi(describeInstancesRequest, null); if (response == null || response.getInstances().size() == 0) { logInfo(String.format("Fail. Can not find instance. InstanceIds: %s", JSON.toJSONString(instanceIds))); return instances; } instances.addAll(response.getInstances()); offset += response.getPageSize(); } return instances; } private Map<String, InstanceExpiredModel> getFailedInstances() { Map<String, InstanceExpiredModel> failedInstances = new HashMap<String, InstanceExpiredModel>(); for (String instanceId : instanceExpiredModelMap.keySet()) { InstanceExpiredModel instanceExpiredModel = instanceExpiredModelMap.get(instanceId); if (instanceExpiredModel.errorCode != null) { failedInstances.put(instanceId, instanceExpiredModel); } } return failedInstances; } private Map<String, InstanceExpiredModel> getSuccessInstances() { Map<String, InstanceExpiredModel> successInstances = new HashMap<String, InstanceExpiredModel>(); for (String instanceId : instanceExpiredModelMap.keySet()) { InstanceExpiredModel instanceExpiredModel = instanceExpiredModelMap.get(instanceId); if (instanceExpiredModel.errorCode == null && instanceExpiredModel.newExpiredTime != null && !instanceExpiredModel.originalExpiredTime .equals(instanceExpiredModel.newExpiredTime)) { successInstances.put(instanceId, instanceExpiredModel); } } return successInstances; } /** * 调用OpenAPI的方法,这里进行了错误处理 * * @param request AcsRequest, Open API的请求 * @param <T> AcsResponse 请求所对应返回值 * @return 返回OpenAPI的调用结果. 如果调用失败,则会返回null */ private <T extends AcsResponse> T callOpenApi(AcsRequest<T> request, BaseResult errorResult) { IAcsClient client = initClient(); try { T response = client.getAcsResponse(request, false, 0); logInfo(String.format("Success. OpenAPI Action: %s call successfully.", request.getActionName())); return response; } catch (ClientException e) { buildErrResult(errorResult, e); } return null; } /** * 需要填充账号的AccessKey ID,以及账号的Access Key Secret */ private IAcsClient initClient() { IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessSecret); return new DefaultAcsClient(profile); } private void logRenewResult() { logInfo("-------- Renew Instances Result --------"); Map<String, InstanceExpiredModel> failedInstances = getFailedInstances(); if (failedInstances.size() > 0) { logInfo(String.format("Fail. Some instances renew failure, result: %s", JSON.toJSONString(failedInstances, SerializerFeature.PrettyFormat))); Map<String, InstanceExpiredModel> successInstances = getSuccessInstances(); if (successInstances.size() > 0) { logInfo(String.format("Success. Some instances renew success, result: %s", JSON.toJSONString(successInstances, SerializerFeature.PrettyFormat))); } } else { logInfo(String.format("Success. RenewInstance result: %s", JSON.toJSONString( instanceExpiredModelMap, SerializerFeature.PrettyFormat))); } } private static void sleepSomeTime(int sleepTime) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } } private static void buildErrResult(BaseResult errResult, ClientException e) { if (errResult != null) { errResult.errorCode = e.getErrCode(); errResult.requestId = e.getRequestId(); } if (e instanceof ServerException) { logInfo(String.format("Fail. Something with your connection with Aliyun go incorrect. ErrorCode: %s", e.getErrCode())); } else { logInfo(String.format("Fail. Business error. ErrorCode: %s, RequestId: %s", e.getErrCode(), e.getRequestId())); } } private static void logInfo(String message) { System.out.println(message); } private List<String> describeNeedRenewInstances() { String instanceExpiredStartTimeUtc = "2018-10-21T16:00Z"; String instanceExpiredEndTimeUtc = "2018-12-01T16:00Z"; List<String> instanceIds = new ArrayList<String>(); int pageSize = 100; int pageNumber = 1; int totalCount = 1; while (instanceIds.size() < totalCount) { DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest(); describeInstancesRequest.setRegionId(regionId); describeInstancesRequest.setFilter3Key(DESCRIBE_INSTANCES_FILTER_KEY_EXPIRED_START_TIME); describeInstancesRequest.setFilter3Value(instanceExpiredStartTimeUtc); describeInstancesRequest.setFilter4Key(DESCRIBE_INSTANCES_FILTER_KEY_EXPIRED_END_TIME); describeInstancesRequest.setFilter4Value(instanceExpiredEndTimeUtc); describeInstancesRequest.setInstanceChargeType(INSTANCE_CHARGE_TYPE_PREPAID); describeInstancesRequest.setPageSize(pageSize); describeInstancesRequest.setPageNumber(pageNumber); DescribeInstancesResponse response = callOpenApi(describeInstancesRequest, null); if (response == null || response.getTotalCount() == 0) { logInfo("Fail. DescribeNeedRenewInstances occurred error or response.getTotalCount() == 0"); return instanceIds; } for (DescribeInstancesResponse.Instance instance : response.getInstances()) { instanceIds.add(instance.getInstanceId()); } totalCount = response.getTotalCount(); pageNumber++; } logInfo(String.format("Success. DescribeNeedRenewInstances result: %s", instanceIds.toString())); return instanceIds; } class BaseResult { public String errorCode; public String requestId; } class InstanceExpiredModel extends BaseResult { public String instanceId; public String originalExpiredTime; public String newExpiredTime; } }
执行结果,用账户余额支付了一月个的续费
Success. OpenAPI Action: DescribeInstances call successfully. Success. OpenAPI Action: RenewInstance call successfully. Success. OpenAPI Action: DescribeInstances call successfully. -------- Renew Instances Result -------- Success. RenewInstance result: { "i-m**********":{ "instanceId":"i-m************", "newExpiredTime":"2019-01-05T16:00Z", "originalExpiredTime":"2018-12-05T16:00Z" } }