附加弹性网卡

本文展示了如何通过调用阿里云ECS Java SDK来附加弹性网卡。

操作场景

附加弹性网卡为异步操作,获得返回结果仅代表附加弹性网卡请求发送成功,附加弹性网卡是否成功有两种方式可以获取。您可以根据业务场景,选择不同的示例。

  • 示例1:适用于对弹性网卡附加时延要求不高、资源量较小的场景,通过轮询网卡状态来获取弹性网卡操作结果。如接口被限流,建议使用示例2的方案。

  • 示例2:适用于对弹性网卡附加时延要求较高、资源量较大的场景,通过事件驱动架构方式来获取弹性网卡操作结果。该方式使用MNS来获取消息,会产生一定的费用。

注意事项

  • 弹性网卡必须处于可用Available)状态,一个弹性网卡只能附加到一台实例上。

  • 实例需处于运行中(Running)或者已停止(Stopped)状态。

  • 实例与弹性网卡所在的交换机必须属于同一可用区、同一专有网络VPC。

示例1

适用于对弹性网卡附加时延要求不高、资源量较小的场景,通过轮询网卡状态来获取弹性网卡操作结果。

  1. 发送附加弹性网卡命令。

  2. 轮询弹性网卡查询接口,查询弹性网卡状态,判断是否附加成功。

说明
  • 轮询弹性网卡查询建议采用退避策略,时间间隔采用2、1、1、1秒。

  • 轮询弹性网卡查询接口限制在60次/秒。

import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.AttachNetworkInterfaceRequest;
import com.aliyun.ecs20140526.models.AttachNetworkInterfaceResponse;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesRequest;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesResponse;
import com.aliyun.ecs20140526.models.DescribeNetworkInterfacesResponseBody.DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;

/**
 * 该示例基于轮询弹性网卡查询接口获取弹性网卡操作结果
 */
public class AttachNetworkInterfaceWithEniDescribe {

    private static final String ENI_STATUS_INUSE = "InUse";
    private static final String ENI_STATUS_AVAILABLE = "Available";
    private static final String ENI_STATUS_ATTACHING = "Attaching";
    private static final long DESC_INTERVAL_MS = 2000;

    /**
     * attach eni
     *
     * @param regionId
     * @param instanceId
     * @param eniId
     * @return
     */
    public static AttachNetworkInterfaceResponse attachNetworkInterface(Client ecsClient, String regionId,
        String instanceId, String eniId) {
        AttachNetworkInterfaceResponse response = null;
        try {
            AttachNetworkInterfaceRequest request = new AttachNetworkInterfaceRequest();
            request.setRegionId(regionId);
            request.setInstanceId(instanceId);
            request.setNetworkInterfaceId(eniId);

            RuntimeOptions runtime = new RuntimeOptions();//用来设置个性化的策略
            response = ecsClient.attachNetworkInterfaceWithOptions(request, runtime);
            System.out.printf(
                "attach network interface %s to ecs instance %s send request success. Request id is %s.%n",
                eniId, instanceId, response.getBody().getRequestId());
        } catch (TeaException te) {
            System.out.println("ErrCode:" + te.getCode());
            System.out.println("ErrMsg:" + te.getMessage());
            System.out.println("RequestId:" + te.getData().get("RequestId"));
        } catch (Exception e) {
            System.out.println("ErrCode:" + e.getMessage());
        }
        return response;
    }

    /**
     * describe eni
     *
     * @param regionId
     * @param eniId
     * @return
     */
    public static DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet describeNetworkInterface(
        Client ecsClient, String regionId, String eniId) {
        DescribeNetworkInterfacesRequest request = new DescribeNetworkInterfacesRequest();
        request.setRegionId(regionId);
        request.setNetworkInterfaceId(Collections.singletonList(eniId));
        List<DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet> networkInterfaceSetList;
        try {
            RuntimeOptions runtime = new RuntimeOptions();//用来设置个性化的策略
            DescribeNetworkInterfacesResponse response = ecsClient.describeNetworkInterfacesWithOptions(request,
                runtime);
            networkInterfaceSetList = response.getBody().getNetworkInterfaceSets().getNetworkInterfaceSet();
            if (networkInterfaceSetList != null && networkInterfaceSetList.size() > 0) {
                return networkInterfaceSetList.get(0);
            }
        } catch (TeaException te) {
            System.out.println("ErrCode:" + te.getCode());
            System.out.println("ErrMsg:" + te.getMessage());
            System.out.println("RequestId:" + te.getData().get("RequestId"));
        } catch (Exception e) {
            System.out.println("ErrCode:" + e.getMessage());
        }
        return null;
    }

    /**
     * Check whether eni successfully attached to ecs instance with max retry count
     *
     * @param ecsClient
     * @param regionId
     * @param eniId
     * @param maxDescTimes
     * @return
     */
    public static boolean isAttachNetworkInterfaceSuccess(Client ecsClient, String regionId, String eniId,
        int maxDescTimes) {
        boolean result = false;
        for (int i = 0; i < maxDescTimes; i++) {
            DescribeNetworkInterfacesResponseBodyNetworkInterfaceSetsNetworkInterfaceSet networkInterface
                = describeNetworkInterface(ecsClient, regionId, eniId);
            if (Objects.isNull(networkInterface)) {
                System.out.println("DescribeNetworkInterfaces return null, please check your input.");
                break;
            }
            if (ENI_STATUS_INUSE.equals(networkInterface.getStatus())) {
                result = true;
                break;
            } else if (ENI_STATUS_AVAILABLE.equals(networkInterface.getStatus())) {
                break;
            } else if (ENI_STATUS_ATTACHING.equals(networkInterface.getStatus())) {
                System.out.printf("This is the %s times describe networkInterface, eni id %s is still attaching.%n",
                    i + 1, eniId);
            } else {
                System.out.printf(
                    "This is the %s times describe networkInterface, eni id %s status is %s, please check before "
                        + "attach.%n",
                    i + 1, eniId, networkInterface.getStatus());
                break;
            }
            interval(DESC_INTERVAL_MS);
        }
        return result;
    }

    public static void interval(long intervalMs) {
        try {
            Thread.sleep(intervalMs);
        } catch (InterruptedException ignored) {

        }
    }

    /**
     * 使用AK&SK初始化账号Client
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @return Client
     * @throws Exception
     */
    public static Client createClient(String accessKeyId, String accessKeySecret,
        String endPoint) throws Exception {
        Config config = new Config()
            // 必填,您的 AccessKey ID
            .setAccessKeyId(accessKeyId)
            // 必填,您的 AccessKey Secret
            .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = endPoint;
        return new Client(config);
    }

    public static void main(String[] args) throws Exception {
        String accessId = "<yourAccessId>";
        String accessKey = "<yourAccessKey>";
        String ecsEndpoint = "<yourEcsEndPoint>";
        String regionId = "<regionId>";
        String eniId = "<yourEniId>";
        String ecsInstanceId = "<yourEcsInstanceId>";

        int maxRetryCnt = 3;

        Client ecsClient = createClient(accessId, accessKey, ecsEndpoint);

        attachNetworkInterface(ecsClient, regionId, ecsInstanceId, eniId);
        if (isAttachNetworkInterfaceSuccess(ecsClient, regionId, eniId, maxRetryCnt)) {
            System.out.printf(
                "Async attach network interface %s to ecs instance success.", eniId);
        } else {
            System.out.printf(
                "Async attach network interface %s to ecs instance fail. Please try again.", eniId);
        }
    }
}

示例2

适用于对弹性网卡附加时延要求较高、资源量较大的场景,通过事件驱动架构方式来获取弹性网卡操作结果。该方式使用MNS来获取消息,会产生一定的费用。MNS费用详见价格说明

准备工作

  1. 创建队列,具体操作,请参见创建队列

    本示例中,自定义队列名称为eni-operate-completed-event,其他配置项保持默认配置。

  2. 创建系统事件报警规则,具体操作,请参见创建系统事件报警规则

    本示例中,您需要注意以下参数配置。

    • 报警规则名称:自定义名称。本示例中,自定义事件通知名称为eni-event-test-rule。

    • 产品类型:选择云服务器ECS

    • 事件类型:选择状态通知

    • 事件等级:选择信息。事件名称:选择网卡操作完成。资源范围:本示例保持默认配置。您可以根据需要自行设置。

    • 报警方式:本示例仅选中消息服务队列,并选择已创建的eni-operate-completed-event队列,设置地域队列

示例代码

示例代码通过监听MNS消息来获取弹性网卡操作结果。

  1. 发送附加弹性网卡命令。

  2. 通过接收MNS消息获取弹性网卡附加结果。

相关文档

AttachNetworkInterface

阿里云首页 云服务器 ECS 相关技术圈