开发者社区> 朴实无华> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

AutoScaling 与函数计算结合,赋予更丰富的弹性能力

简介: 阿里云弹性伸缩服务目前已经与大量的云产品相结合,赋予了灵活的弹性能力,在此基础上,弹性伸缩服务进一步与 MNS & FC 结合,实现了更加灵活的自动化管理,赋予了我们更加丰富的弹性能力。
+关注继续查看

目前,弹性伸缩服务已经接入了负载均衡(SLB)、云数据库RDS 等云产品,但是暂未接入 云数据库Redis,有时候我们可能会需要弹性伸缩服务在扩缩容的时候自动将扩缩容涉及到的 ECS 实例私网 IP 添加到 Redis 白名单或者从 Redis 白名单中移除。本文将给出上述场景的最佳实践,向您介绍如何通过 AutoSclaing -> LifecycleHook -> MNS -> FC 的方式实现伸缩组发生扩容时自动将扩容出来的 ECS 实例私网 IP 添加到 Redis 白名单中,您可以在此基础上,根据您的业务需求进行扩展。

函数计算(FC)简介

阿里云函数计算是事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询、性能监控、报警等功能。借助于函数计算,您可以快速构建任何类型的应用和服务,无需管理和运维。而且,您只需要为代码实际运行所消耗的资源付费,代码未运行则不产生费用。更多关于函数计算的相关信息,您可以通过 函数计算官方文档 进行了解。

消息服务(MNS)简介

阿里云消息服务(Message Service,简称 MNS)是一种高效、可靠、安全、便捷、可弹性扩展的分布式消息服务。MNS能够帮助应用开发者在他们应用的分布式组件上自由的传递数据、通知消息,构建松耦合系统。更多关于消息服务的相关信息,您可以通过 消息服务官方文档 进行了解。

最佳实践

前提条件

在进行以下操作前,您需要先开通 函数计算服务FC消息服务MNS弹性伸缩服务AutoScaling,接下来配置我们需要用的 FC、MNS、AutoScaling 相关信息

配置 MNS

登录 MNS控制台,创建 MNS 主题(作为函数计算的触发器),如下图所示:

image

同样的,创建 MNS 队列,MNS 队列作为函数计算执行结果接收器,队列名称会在代码中进行配置。

配置 FC

登录FC控制台,新建服务,如下图所示:

image

服务创建好以后,新增函数,如下图所示:

image

点击新增函数,弹出新建函数对话框,如下图所示:

image

选择函数语言,并选择空白模板,跳转到触发器配置界面,如下图所示:

image

配置好触发器类型、触发器名称以及对应的 MNS 主题(MNS 主题与 FC 所属的地域最好相同),点击下一步,跳转到基础管理配置界面,如下图所示:

image
image

所在服务默认会选择当前服务,不用改变,填写函数名称,选择运行环境,通过代码包上传的方式上传提前测试好的 java jar包(即触发函数计算时需要执行的运行的程序,本文最后会给出示例jar包),按照说明填写好函数入口,点击下一步,跳转到模版授权管理界面,如下图所示:

image
image

首先授予函数运行所需要的权限,授权时候应遵循权限最小化原则,防止权限过大,如上图步骤1、2所示,再授予 MNS 触发 FC 所需的权限,如上图步骤3、4所示,最后点击下一步,跳转到信息核对界面,如下图所示:

image

核对信息无误,点击创建,函数创建完成。

关于函数计算的配置过程,您可以通过 FC Hello World示例 进行了解。

创建云数据库 Redis

登录 Redis控制台,选择和 MNS 、FC 相同的地域,创建 Redis 实例。实例创建完以后,查看实例的白名单设置,如下图所示:
image

配置 AutoScaling

登录 弹性伸缩控制台,创建好伸缩组以及伸缩配置以后,创建生命周期挂钩(LifecycleHook),如下图所示:

image

上图中,在左侧导航栏选择生命周期挂钩,点击创建生命周期挂钩按钮,填写名称,选择生命周期挂钩对应的伸缩活动类型,配置生命周期挂钩对应的 MNS 通知为 MNS 主题,并且选择的主题为 FC 触发器对应的主题,最后点击创建按钮,生命周期挂钩函数创建完成,如下图所示:

image

在伸缩组发生扩容伸缩活动时,实例创建完成并运行起来以后,生命周期挂钩会被触发,并发送伸缩活动相关信息到生命周期挂钩配置的 MNS 主题上,挂起当前的伸缩活动,直到生命周期挂钩超时或者被提前结束。生命周期挂钩活动结束以后,伸缩活动继续执行,扩容出来的 ECS 实例会被挂载到负载均衡实例上(如果伸缩组配置了负载均衡实例的话)。关于生命周期挂钩功能的详细说明,您可以通过云栖博客 AutoScaling 生命周期挂钩功能 进行详细了解。

触发扩容伸缩活动

首先,我们通过触发扩容伸缩活动的方式,创建 10 台 ECS 实例,对应的伸缩活动如下图所示:

image

然后我们登录 MNS控制台,查看队列接收到的 FC 执行结果消息,如下图所示:

image

上述消息中 success 为 true,表示函数计算执行成功(即 ECS 实例私网 IP 添加到 Redis 白名单成功),消息体中还包括了当前生命周期挂钩活动对应的 LifecycleHookId LifecycleActionToken 参数信息,您可以根据相关参数信息调用 CompleteLifecycleAction 接口提前结束生命周期活动。

最后,我们登录 云数据库Redis控制台,查看当前的 Redis 白名单信息,如下图所示:

image

从上图可以看出,弹性伸缩扩容活动创建出来的 ECS 实例私网 IP 成功添加到 Redis 白名单中。

至此,通过 AutoScaling -> LifecycleHook -> MNS -> FC 实现 Redis 白名单自动添加的过程结束,整体过程如下:

  1. 弹性伸缩组触发扩容伸缩活动,扩容 ECS 实例,扩容活动触发生命周期挂钩
  2. 生命周期挂钩将扩容活动挂起,同时发送消息到 MNS 主题
  3. MNS 主题接收到消息以后将消息作为输入信息触发 FC,FC 被触发以后执行预置业的 JAVA 函数
  4. JAVA 函数获取 FC 触发器的输入信息,信息中包括了本次伸缩活动对应的 ECS 实例 ID信息,通过接口获取 ECS 实例私网 IP 以后添加到 Redis default 分组白名单中
  5. 最后,函数执行结果发送到代码中配置好的 MNS 队列中

上述过程仅作为一个参考的 Demo,进一步实现自动化管理,还需要我们自己编程实现,如编程的方式消费 MNS 队列中的消息,获取执行结果与 LifecycleHookId LifecycleActionToken等参数信息提前结束生命周期挂钩活动等。

FC 预置 JAVA 代码解析

FC 预置函数为 JAVA 代码,通过 Maven 管理,对应的代码及依赖如下:

Example.java

package fc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.model.Message;
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.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.r_kvstore.model.v20150101.DescribeSecurityIpsRequest;
import com.aliyuncs.r_kvstore.model.v20150101.DescribeSecurityIpsResponse;
import com.aliyuncs.r_kvstore.model.v20150101.ModifySecurityIpsRequest;
import model.FCResult;
import model.HookModel;
import model.MnsMessageModel;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Example implements StreamRequestHandler {

    /**
     * 专有网络类型,此参数不用变
     */
    private static final String  VPC_NETWORK                 = "vpc";

    private static final String  CHAR_SET                    = "UTF-8";

    /**
     * 接收input数组大小,4096通常够用
     */
    private static final Integer MAX_BYTE_LENGTH             = 4096;

    /**
     * REDIS 白名单默认分组
     */
    private static final String  DEFAULT_SECURITY_GROUP_NAME = "default";

    /**
     * REDIS 修改白名单的模式
     */
    private static final String  MODIFY_MODE_APPEND          = "Append";

    /**
     * MNS 客户端发送消息地址
     */
    private static final String  MNS_END_POINT               = "http://%s.mns.%s.aliyuncs.com/";

    /**
     * 待添加的REDIS实例ID,根据个人情况替换
     */
    private static final String  REDIS_ID                    = "";

    /**
     * 接收本次函数计算执行结果的队列名称,根据个人情况替换
     */
    private static final String  QUEUE_NAME                  = "wujin-fc-callback";

    /**
     * 阿里云账号UID,根据跟人情况替换
     */
    private static final Long    USER_ID                     = 1111111111111111111L;

    /**
     * 伸缩组 MNS FC 所属的region,根据个人情况替换
     */
    private static final String  REGION_ID                   = "cn-hangzhou";

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
        FCResult result = new FCResult();
        String akId = context.getExecutionCredentials().getAccessKeyId();
        String akSecret = context.getExecutionCredentials().getAccessKeySecret();
        String securityToken = context.getExecutionCredentials().getSecurityToken();
        try {
            //获取MNS触发函数计算时输入的内容
            String input = readInput(inputStream);
            MnsMessageModel mnsMessageModel = JSON.parseObject(input,
                    new TypeReference<MnsMessageModel>() {
                    });
            if (mnsMessageModel == null) {
                result.setSuccess(false);
                result.setMessage("mnsMessageModel is null");
                sendMns(akId, akSecret, securityToken, result.toString());
                return;
            }
            HookModel contentModel = mnsMessageModel.getContent();
            if (contentModel == null) {
                result.setSuccess(false);
                result.setMessage("contentModel is null");
                sendMns(akId, akSecret, securityToken, result.toString());
                return;
            }
            IAcsClient client = buildClient(akId, akSecret, securityToken);
            //获取本次伸缩活动对应实例的私网IP
            List<String> privateIps = getInstancesPrivateIps(contentModel.getInstanceIds(), client);
            if (CollectionUtils.isEmpty(privateIps)) {
                result.setSuccess(false);
                result.setMessage("privateIps is empty");
                sendMns(akId, akSecret, securityToken, result.toString());
                return;
            }
            List<String> needAppendIps = filterPrivateIpsForAppend(privateIps, client);
            if (!CollectionUtils.isEmpty(needAppendIps)) {
                modifySecurityIps(client, needAppendIps);
                result.setLifecycleHookId(contentModel.getLifecycleHookId());
                result.setLifecycleActionToken(contentModel.getLifecycleActionToken());
                sendMns(akId, akSecret, securityToken, result.toString());
            }
        } catch (Exception ex) {
            result.setSuccess(false);
            result.setMessage(ex.getMessage());
            sendMns(akId, akSecret, securityToken, result.toString());
        }
    }

    /**
     * 构建请求 ECS Redis 接口客户端
     *
     * @param akId
     * @param akSecret
     * @param securityToken
     * @return
     */
    private IAcsClient buildClient(String akId, String akSecret, String securityToken) {
        IClientProfile clientProfile = DefaultProfile.getProfile(REGION_ID, akId, akSecret,
                securityToken);
        return new DefaultAcsClient(clientProfile);
    }

    /**
     * 将执行结果发送消息到MNS
     *
     * @param ak
     * @param aks
     * @param securityToken
     * @param msg
     */
    private void sendMns(String ak, String aks, String securityToken, String msg) {
        MNSClient client = null;
        try {
            CloudAccount account = new CloudAccount(ak, aks,
                    String.format(MNS_END_POINT, USER_ID, REGION_ID), securityToken);
            client = account.getMNSClient();
            CloudQueue queue = client.getQueueRef(QUEUE_NAME);
            Message message = new Message();
            message.setMessageBody(msg);
            queue.putMessage(message);
        } finally {
            if (client != null) {
                client.close();
            }
        }
    }

    /**
     * 过滤出需要添加到redis的私网IP
     *
     * @param privateIps 过滤以前的私网IP
     * @param client
     * @return
     * @throws ClientException
     */
    private List<String> filterPrivateIpsForAppend(List<String> privateIps, IAcsClient client)
            throws ClientException {
        List<String> needAppendIps = new ArrayList<>();
        if (CollectionUtils.isEmpty(privateIps)) {
            return needAppendIps;
        }
        DescribeSecurityIpsRequest request = new DescribeSecurityIpsRequest();
        request.setInstanceId(REDIS_ID);
        DescribeSecurityIpsResponse response = client.getAcsResponse(request);
        List<DescribeSecurityIpsResponse.SecurityIpGroup> securityIpGroups = response
                .getSecurityIpGroups();
        if (CollectionUtils.isEmpty(securityIpGroups)) {
            return privateIps;
        }
        for (DescribeSecurityIpsResponse.SecurityIpGroup securityIpGroup : securityIpGroups) {
            if (!securityIpGroup.getSecurityIpGroupName().equals(DEFAULT_SECURITY_GROUP_NAME)) {
                continue;
            }
            String securityIps = securityIpGroup.getSecurityIpList();
            if (securityIps == null) {
                continue;
            }
            String[] securityIpList = securityIps.split(",");
            List<String> existIps = Arrays.asList(securityIpList);
            if (CollectionUtils.isEmpty(existIps)) {
                continue;
            }
            for (String ip : privateIps) {
                if (!existIps.contains(ip)) {
                    needAppendIps.add(ip);
                }
            }
        }
        return privateIps;
    }

    /**
     * 修改REDIS实例DEFAULT分组私网IP白名单
     *
     * @param client
     * @param needAppendIps
     * @throws ClientException
     */
    private void modifySecurityIps(IAcsClient client, List<String> needAppendIps)
            throws ClientException {
        if (CollectionUtils.isEmpty(needAppendIps)) {
            return;
        }
        ModifySecurityIpsRequest request = new ModifySecurityIpsRequest();
        request.setInstanceId(REDIS_ID);
        String ip = StringUtils.join(needAppendIps.toArray(), ",");
        request.setSecurityIps(ip);
        request.setSecurityIpGroupName(DEFAULT_SECURITY_GROUP_NAME);
        request.setModifyMode(MODIFY_MODE_APPEND);
        client.getAcsResponse(request);
    }

    /**
     * 获取输入,并base64解码
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    private String readInput(InputStream inputStream) throws IOException {
        try {
            byte[] bytes = new byte[MAX_BYTE_LENGTH];
            int tmp;
            int len = 0;
            //循环读取所有内容
            while ((tmp = inputStream.read()) != -1 && len < MAX_BYTE_LENGTH) {
                bytes[len] = (byte) tmp;
                len++;
            }
            inputStream.close();
            byte[] act = new byte[len];
            System.arraycopy(bytes, 0, act, 0, len);
            return new String(Base64.decodeBase64(act), CHAR_SET);
        } finally {
            inputStream.close();
        }
    }

    /**
     * 获取实例列表对应的私网IP,并限制每次请求实例数量不超过100
     *
     * @param instanceIds 实例列表
     * @param client 请求客户端
     * @return
     * @throws Exception
     */
    public List<String> getInstancesPrivateIps(List<String> instanceIds, IAcsClient client)
            throws Exception {
        List<String> privateIps = new ArrayList<>();
        if (CollectionUtils.isEmpty(instanceIds)) {
            return privateIps;
        }
        int size = instanceIds.size();
        int queryNumberPerTime = 100;
        int batchCount = (int) Math.ceil((float) size / (float) queryNumberPerTime);
        //support 100 instance
        for (int i = 1; i <= batchCount; i++) {
            int fromIndex = queryNumberPerTime * (i - 1);
            int toIndex = Math.min(queryNumberPerTime * i, size);
            List<String> subList = instanceIds.subList(fromIndex, toIndex);
            DescribeInstancesRequest request = new DescribeInstancesRequest();
            request.setInstanceIds(JSON.toJSONString(subList));
            DescribeInstancesResponse response = client.getAcsResponse(request);
            List<DescribeInstancesResponse.Instance> instances = response.getInstances();
            if (CollectionUtils.isEmpty(instances)) {
                continue;
            }
            for (DescribeInstancesResponse.Instance instance : instances) {
                String privateIp = getPrivateIp(instance);
                if (privateIp != null) {
                    privateIps.add(privateIp);
                }
            }
        }
        return privateIps;
    }

    /**
     * 从 DescribeInstancesResponse.Instance 中解析出私网 IP
     *
     * @param instance DescribeInstancesResponse.Instance
     */
    private String getPrivateIp(DescribeInstancesResponse.Instance instance) {
        String privateIp = null;
        if (VPC_NETWORK.equalsIgnoreCase(instance.getInstanceNetworkType())) {
            DescribeInstancesResponse.Instance.VpcAttributes vpcAttributes = instance
                    .getVpcAttributes();
            if (vpcAttributes != null) {
                List<String> privateIpAddress = vpcAttributes.getPrivateIpAddress();
                if (!CollectionUtils.isEmpty(privateIpAddress)) {
                    privateIp = privateIpAddress.get(0);
                }
            }
        } else {
            List<String> innerIpAddress = instance.getInnerIpAddress();
            if (!CollectionUtils.isEmpty(innerIpAddress)) {
                privateIp = innerIpAddress.get(0);
            }
        }
        return privateIp;
    }
}

代码中涉及到的 Model 文件

FCResult.java

package model;

import com.alibaba.fastjson.JSON;

public class FCResult {

  private boolean success = true;

  private String  lifecycleHookId;

  private String  lifecycleActionToken;

  private String  message;

  public boolean isSuccess() {
      return success;
  }

  public void setSuccess(boolean success) {
      this.success = success;
  }

  public String getLifecycleHookId() {
      return lifecycleHookId;
  }

  public void setLifecycleHookId(String lifecycleHookId) {
      this.lifecycleHookId = lifecycleHookId;
  }

  public String getLifecycleActionToken() {
      return lifecycleActionToken;
  }

  public void setLifecycleActionToken(String lifecycleActionToken) {
      this.lifecycleActionToken = lifecycleActionToken;
  }

  public String getMessage() {
      return message;
  }

  public void setMessage(String message) {
      this.message = message;
  }

  @Override
  public String toString() {
      return JSON.toJSONString(this);
  }
}

HookModel.java

package model;

import java.util.List;

public class HookModel {

    private String            lifecycleHookId;

    private String            lifecycleActionToken;

    private String            lifecycleHookName;

    private String            scalingGroupId;

    private String            scalingGroupName;

    private String            lifecycleTransition;

    private String            defaultResult;

    private String            requestId;

    private String            scalingActivityId;

    private List<String>      instanceIds;

    public String getLifecycleHookId() {
        return lifecycleHookId;
    }

    public void setLifecycleHookId(String lifecycleHookId) {
        this.lifecycleHookId = lifecycleHookId;
    }

    public String getLifecycleActionToken() {
        return lifecycleActionToken;
    }

    public void setLifecycleActionToken(String lifecycleActionToken) {
        this.lifecycleActionToken = lifecycleActionToken;
    }

    public String getLifecycleHookName() {
        return lifecycleHookName;
    }

    public void setLifecycleHookName(String lifecycleHookName) {
        this.lifecycleHookName = lifecycleHookName;
    }

    public String getScalingGroupId() {
        return scalingGroupId;
    }

    public void setScalingGroupId(String scalingGroupId) {
        this.scalingGroupId = scalingGroupId;
    }

    public String getScalingGroupName() {
        return scalingGroupName;
    }

    public void setScalingGroupName(String scalingGroupName) {
        this.scalingGroupName = scalingGroupName;
    }

    public String getLifecycleTransition() {
        return lifecycleTransition;
    }

    public void setLifecycleTransition(String lifecycleTransition) {
        this.lifecycleTransition = lifecycleTransition;
    }

    public String getDefaultResult() {
        return defaultResult;
    }

    public void setDefaultResult(String defaultResult) {
        this.defaultResult = defaultResult;
    }

    public String getRequestId() {
        return requestId;
    }

    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }

    public String getScalingActivityId() {
        return scalingActivityId;
    }

    public void setScalingActivityId(String scalingActivityId) {
        this.scalingActivityId = scalingActivityId;
    }

    public List<String> getInstanceIds() {
        return instanceIds;
    }

    public void setInstanceIds(List<String> instanceIds) {
        this.instanceIds = instanceIds;
    }
}

MnsMessageModel.java

package model;

public class MnsMessageModel {

    private String    userId;

    private String    regionId;

    private String    resourceArn;

    private HookModel content;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getRegionId() {
        return regionId;
    }

    public void setRegionId(String regionId) {
        this.regionId = regionId;
    }

    public String getResourceArn() {
        return resourceArn;
    }

    public void setResourceArn(String resourceArn) {
        this.resourceArn = resourceArn;
    }

    public HookModel getContent() {
        return content;
    }

    public void setContent(HookModel content) {
        this.content = content;
    }
}

Maven 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.aliyun.fc.wujin</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-ecs</artifactId>
            <version>4.10.1</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.fc.runtime</groupId>
            <artifactId>fc-java-core</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-r-kvstore</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.25</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>com.springsource.org.apache.commons.lang</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.mns</groupId>
            <artifactId>aliyun-sdk-mns</artifactId>
            <version>1.1.8.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <appendAssemblyId>false</appendAssemblyId> <!-- this is used for not append id to the jar name -->
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

上述java文件中,Example.java 文件在包名为 fc 的目录下,FCResult.java HookModel.java MnsMessageModel.java 三个文件在包名为 model 的目录下,package fc 与 package model 处于同级目录。
Example.java 文件需要根据实际情况对相关参数进行替换,QUEUE_NAME 参数定义了接收函数执行结果的 MNS 队列,我们在 配置 MNS 章节已经提前创建好了。
参数替换完成以后,可以参考 FC Java 编程说明 重新打包并上传您的 jar 包即可,上传方法如下图所示:
image

写在最后

通过 AutoScaling -> LifecycleHook -> MNS -> FC 的方式,您可以具备更加丰富的弹性能力,从而更加灵活地管理您伸缩组内的资源。

上述代码仅供参考,具体实现需要结合具体业务进行测试改造。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
函数计算实现弹性音视频处理系统
使用函数计算搭建音视频处理应用,快速构建高可用高弹性音视频处理系统。
0 0
借力阿里云函数计算极致弹性,石墨文档助力 20 万家企业远程复工
作为中国第一款支持云端实时协作的企业办公服务软件,石墨文档在疫情防控期间,借助阿里云函数计算极值弹性,不仅全面助力企业组织高效协同运转,守护员工健康;更成为人们爱心传递的利器。
0 0
5分钟快速了解Serverless和云函数计算
5分钟快速了解Serverless和云函数计算
0 0
《函数计算—事件驱动的serverless计算平台》电子版地址
函数计算—事件驱动的serverless计算平台
0 0
基于阿里云 Serverless 函数计算搭建按量付费的 WordPress 网站
Serverless 经过几年的发展,已经和传统服务器一样好用了。我最初接触 Serverless 是在 2020 年的云开发校园合伙人创造营上,当时我基于阿里云云开发平台部署了一个在线工具箱。
0 0
对Serverless函数计算的理解
Serverless的全称是Serverless computing无服务器运算,又被称为函数即服务(Function-as-a-Service,缩写为 FaaS),是云计算的一种模型。以平台即服务(PaaS)为基础,无服务器运算提供一个微型的架构,终端客户不需要部署、配置或管理服务器服务,代码运行所需要的服务器服务皆由云端平台来提供。
0 0
基于函数计算快速部署 Serverless VSCode WebIDE-2
基于函数计算快速部署 Serverless VSCode WebIDE-2
0 0
基于函数计算快速部署 Serverless VSCode WebIDE-1
基于函数计算快速部署 Serverless VSCode WebIDE-1
0 0
基于函数计算快速部署 Serverless VSCode WebIDE
基于函数计算快速部署 Serverless VSCode WebIDE
0 0
Serverless函数计算评测征集令获奖名单
Serverless函数计算评测征集令获奖名单出炉
0 0
+关注
朴实无华
AutoScaling
文章
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
函数计算集团规模化落地实践(3).ppt
立即下载
在线教育/娱乐音视频处理Faas最佳实践
立即下载
触摸云端编程之道-利用函数计算快速构建弹性可扩展的云原生应用
立即下载