【新功能发布】事件监控升级-支持自动化处理云产品异常

本文涉及的产品
函数计算FC,每月15万CU 3个月
公网NAT网关,每月750个小时 15CU
云监控,每月短信1000条
简介: 事件监控发布新版本,支持在云产品的系统事件发生时,分发给您的消息服务队列、函数计算,以便后续自动化处理这些异常。

背景

系统事件监控为用户提供各类云产品产生的系统事件的统一统计和查询入口,使得用户明确知晓云产品的使用状态,让云更透明。

本月的新版本,支持在这些产品的系统事件发生时,分发给您的消息服务队列、函数计算,以便后续自动化处理这些异常。

原理解读

事件发生时,云产品会将事件推送给云监控,云监控收到事件后,检查您是否配置了报警规则,如果有相关配置,会根据报警规则的配置将事件分发到相应渠道。
image

最佳实践分享

如何在ECS宕机时,通过函数计算将EIP迁移到另一台机器上。并且发送事件到消息服务的队列中。

创建函数计算

  1. 登录函数计算控制台:https://fc.console.aliyun.com/overview/cn-shanghai
  2. 新建服务
    image
  3. 新建函数
    image

选择空白函数,不创建触发器,以Java8运行环境为例
image
上传一段EIP从机器A解绑后,绑定到机器B的代码逻辑,jar包中的代码见文章结尾分享。
image

函数入口为com.aliyun.cms.fc.driver.FCDriver::handleRequest
image
无需其他权限设置,点击创建后保存函数

创建消息服务的队列

  1. 登录消息服务控制台:https://mns.console.aliyun.com/#/list/cn-hangzhou
  2. 创建队列
    image

创建云监控系统事件报警

  1. 登录云监控事件监控控制台:https://cloudmonitor.console.aliyun.com/#/eventmonitoring/alarmrules
  2. 创建事件报警规则
    19_24_30__08_06_2018

点击按钮进入创建报警规则页面
19_33_10__08_06_2018

首次使用先点击授权,允许云监控向您的队列和函数发送事件。
19_34_11__08_06_2018

授权后,选择上一步创建好的队列和函数,保存设置。
19_37_06__08_06_2018

调试事件

您可以使用系统事件的调试功能,模拟系统事件的发生,以便验证报警规则中设置的消息服务队列是否能正常接收时间、函数计算的函数是否能正常被触发。

  1. 点击报警规则列表的调试操作,进入调试页面
    22
  2. 选择需要调试的事件,内容中会显示相应的事件内容,可以根据实际情况修改内容中的实例id等字段。
    33
  3. 点击确定按钮,将根据内容发送一个事件,触发函数计算的逻辑、向消息服务队列中写一个事件。

查看结果

  1. 查看消息服务的队列信息
    消息服务队列的列表页点击接收消息,可以看到队列里收到了调试发出的事件。

19_43_57__08_06_2018

  1. 弹性公网IP控制台查看IP已经从一台实例解绑后,重新绑定到另一台实例。
  2. 在函数计算的代码执行模块,可以查询执行结果。
    20_34_49__08_06_2018

示例代码

  • 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.cms</groupId>
    <artifactId>drive-fc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <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-ecs</artifactId>
            <version>4.9.4</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-slb</artifactId>
            <version>3.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.0.3</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.48</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </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 代码

示例包含EIP的解绑、绑定,SLB后端ESC实例的绑定、解绑,磁盘的挂载。试用时请将实例id、AK、SK等信息替换成您的具体信息,示例仅供演示参考,具体事件发生时应做的处理,需要根据您的实际业务决定。

package com.aliyun.cms.fc.driver;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.FunctionComputeLogger;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.ecs.model.v20140526.*;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.slb.model.v20140515.AddBackendServersRequest;
import com.aliyuncs.slb.model.v20140515.AddBackendServersResponse;
import com.aliyuncs.slb.model.v20140515.RemoveBackendServersRequest;
import com.aliyuncs.slb.model.v20140515.RemoveBackendServersResponse;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
public class FCDriver implements StreamRequestHandler 
   private static final String ak = "*";
   private static final String aks = "*";

   /**
    *
    * @param inputStream
    * @param outputStream
    * @param context
    * @throws IOException
    */
   @Override
   public void handleRequest(
           InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
       String input = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
       JSONObject event = JSON.parseObject(input, JSONObject.class);
       context.getLogger().info("receive event message: " + event);
       String product = event.getString("product");
       if ("ECS1".equalsIgnoreCase(product)) {
           handleECS(context.getLogger(), event);
       }
       outputStream.write("ok".getBytes());
   }

   public void handleECS(FunctionComputeLogger logger, JSONObject event) {
       JSONObject content = event.getJSONObject("content");
       String ecsInstanceId = content.getString("ecsInstanceId");
       String regionId = event.getString("regionId");
       String name = event.getString("name");
       String eipId = "eip-*";
       if ("Disk:Stalled:Executing".equalsIgnoreCase(name)){
           unassociateEipAddress(regionId, ecsInstanceId, eipId, logger);
           try {
               TimeUnit.SECONDS.sleep(30);
           } catch (InterruptedException e) {
           }
           associateEipAddress(regionId, "i-****", eipId, logger);
       }else if ("Disk:Stalled:Executed".equalsIgnoreCase(name)){
           unassociateEipAddress(regionId, "i-****", eipId, logger);
           try {
               TimeUnit.SECONDS.sleep(30);
           } catch (InterruptedException e) {
           }
           associateEipAddress(regionId, ecsInstanceId, eipId, logger);
       }else if ("Instance:SystemFailure.Reboot:Executing".equalsIgnoreCase(name)){
           unassociateEipAddress(regionId, ecsInstanceId, eipId, logger);
           try {
               TimeUnit.SECONDS.sleep(30);
           } catch (InterruptedException e) {
           }
           associateEipAddress(regionId, "i-****", eipId, logger);
       }else if ("Instance:SystemFailure.Reboot:Executed".equalsIgnoreCase(name)){
           unassociateEipAddress(regionId, "i-****", eipId, logger);
           try {
               TimeUnit.SECONDS.sleep(30);
           } catch (InterruptedException e) {
           }
           associateEipAddress(regionId, ecsInstanceId, eipId, logger);
       }
   }

   private void associateEipAddress(String regionId, String ecsInstanceId, String eipId, FunctionComputeLogger logger ) {
       DefaultProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);

       try {
           for (int count=0;count<5;count++) {
               DescribeEipAddressesRequest describeEipAddressesRequest = new DescribeEipAddressesRequest();
               describeEipAddressesRequest.setAllocationId(eipId);
               describeEipAddressesRequest.setRegionId(regionId);
               DescribeEipAddressesResponse describeEipAddressesResponse = client.getAcsResponse(describeEipAddressesRequest);
               if (describeEipAddressesResponse!=null&&describeEipAddressesResponse.getEipAddresses()!=null&&"vailable".equalsIgnoreCase(describeEipAddressesResponse.getEipAddresses().get(0).getStatus())){
                   AssociateEipAddressRequest request = new AssociateEipAddressRequest();
                   request.setInstanceId(ecsInstanceId);
                   request.setAllocationId(eipId);
                   try {
                       AssociateEipAddressResponse response = client.getAcsResponse(request);
                       logger.info(String.format("Associate eip %s to ecs %s, requestId:%s, ", eipId, ecsInstanceId, response.getRequestId()));
                   } catch (ClientException e) {
                       logger.info(String.format("Failure of associate eip %s to ecs %s, errorMsg:%s", eipId, ecsInstanceId, e.getLocalizedMessage()));
                   }
                   return;
               }
               TimeUnit.SECONDS.sleep(5);
           }
       } catch (InterruptedException | ClientException e) {
           logger.info(String.format("Failure of describe eip %s, errorMsg:%s", eipId, e.getLocalizedMessage()));
       }
   }

   private void unassociateEipAddress(String regionId, String ecsInstanceId, String eipId, FunctionComputeLogger logger) {
       DefaultProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);

       UnassociateEipAddressRequest request = new UnassociateEipAddressRequest();
       request.setInstanceId(ecsInstanceId);
       request.setAllocationId(eipId);
       try {
           UnassociateEipAddressResponse response = client.getAcsResponse(request);
           logger.info(String.format("Unassociate eip %s to ecs %s, requestId:%s, ", eipId, ecsInstanceId, response.getRequestId()));
       } catch (ClientException e) {
           logger.info(String.format("Failure of unassociate eip %s to ecs %s, errorMsg:%s", eipId, ecsInstanceId, e.getLocalizedMessage()));
       }
   }

   private void addBackendServer(String regionId, String ecsInstanceId, FunctionComputeLogger logger) {
       DefaultProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);
       String lb = "lb-****";
       AddBackendServersRequest request = new AddBackendServersRequest();
       request.setBackendServers(String.format("[{\"ServerId\":\"%s\",\"Weight\":50}]",ecsInstanceId));
       request.setLoadBalancerId(lb);
       try {
           AddBackendServersResponse response = client.getAcsResponse(request);
           logger.info(String.format("add backend server %s to lb %s, requestId:%s, ", ecsInstanceId, lb, response.getRequestId()));
       } catch (ClientException e) {
           logger.info(String.format("failure of add backend server %s to lb %s, errorMsg:%s", ecsInstanceId, lb, e.getLocalizedMessage()));
       }
   }

   private void removeBackendServer(String regionId, String ecsInstanceId, FunctionComputeLogger logger) {
       DefaultProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);
       String lb = "lb-****";
       RemoveBackendServersRequest request = new RemoveBackendServersRequest();
       request.setBackendServers(String.format("[\"%s\"]",ecsInstanceId));
       request.setLoadBalancerId(lb);
       try {
           RemoveBackendServersResponse response = client.getAcsResponse(request);
           logger.info(String.format("remove backend server %s to lb %s, requestId:%s, ", ecsInstanceId, lb, response.getRequestId()));
       } catch (ClientException e) {
           logger.info(String.format("failure of remove backend server %s to lb %s, errorMsg:%s", ecsInstanceId, lb, e.getLocalizedMessage()));
       }
   }

   private void mountDisk(String regionId, String ecsInstanceId, String diskId, FunctionComputeLogger logger) {
       logger.info("prepare mount diskId:"+diskId);
       AttachDiskRequest request = new AttachDiskRequest();
       request.setDiskId(diskId);
       request.setInstanceId(ecsInstanceId);
       IClientProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);
       try {
           AttachDiskResponse response = client.getAcsResponse(request);
           logger.info("mount disk result:" + JSON.toJSONString(response));
       } catch (ClientException e) {
           logger.error("mount failure, diskId:" + diskId + e.getMessage());
       }

   }

   private void unmountDisk(String regionId, String ecsInstanceId, String diskId, FunctionComputeLogger logger) {
       logger.info("prepare mount diskId:"+diskId);
       DetachDiskRequest request = new DetachDiskRequest();
       request.setDiskId(diskId);
       request.setInstanceId(ecsInstanceId);
       IClientProfile profile = DefaultProfile.getProfile(regionId, ak, aks);
       IAcsClient client = new DefaultAcsClient(profile);
       try {
           DetachDiskResponse response = client.getAcsResponse(request);
           logger.info("unmount disk result:" + JSON.toJSONString(response));
       } catch (ClientException e) {
           logger.error("unmount failure, diskId:" + diskId);
       }
   }
}

欢迎扫描下方二维码,加入云监控用户支持群。
image

相关实践学习
基于云监控实现的监控系统
通过阿里云云监控功能给非阿里云主机安装监控插件,从而实现对非阿里云主机的各项指标进行监控和管理,在配置报警规则和报警人的情况下,能对特定的场景做出报警反应通知到报警人的手机上。
目录
相关文章
|
3月前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的全方位实践
本文深入探讨了构建高效运维体系的关键要素,从监控、日志管理、自动化工具、容器化与微服务架构、持续集成与持续部署(CI/CD)、虚拟化与云计算以及安全与合规等方面进行了全面阐述。通过引入先进的技术和方法,结合实际案例和项目经验,为读者提供了一套完整的运维解决方案,旨在帮助企业提升运维效率,降低运营成本,确保业务稳定运行。
|
13天前
|
缓存 监控 安全
公司电脑监控软件的 Gradle 构建自动化优势
在数字化办公环境中,公司电脑监控软件面临代码更新频繁、依赖管理和构建复杂等挑战。Gradle 构建自动化工具以其强大的依赖管理、灵活的构建脚本定制及高效的构建缓存与增量构建特性,显著提升了软件开发效率和质量,支持软件的持续更新与优化,满足企业对员工电脑使用情况的监控与管理需求。
26 3
|
1月前
|
监控 Devops jenkins
自动化部署与监控:打造高效的DevOps流程
【10月更文挑战第24天】在追求快速迭代和持续交付的软件开发时代,DevOps成为提升团队效率的关键。本文深入探讨如何构建一个高效的DevOps流程,包括自动化部署、监控和故障排除等关键环节。通过实际案例,我们将学习如何利用工具简化运维任务,确保系统稳定运行,并快速响应生产问题。
68 2
|
2月前
|
运维 监控 测试技术
构建高效运维体系:从监控到自动化的实践之路
【10月更文挑战第9天】 在当今信息技术飞速发展的时代,运维作为保障系统稳定性与效率的关键角色,正面临前所未有的挑战。本文将探讨如何通过构建一个高效的运维体系来应对这些挑战,包括监控系统的搭建、自动化工具的应用以及故障应急处理机制的制定。我们将结合具体案例,分析这些措施如何帮助提升系统的可靠性和运维团队的工作效率。
62 1
|
2月前
|
存储 消息中间件 运维
架构升级的救星!流量回放自动化测试的必备指南
大家好,我是小米,一名29岁的技术宅。今天分享一个物联网领域的实用技能——流量回放自动化测试。系统重构后,测试工作量巨大,本文介绍如何通过日志收集和数据回放进行自动化测试,包括离线、实时和并行回放模式,帮助快速定位Bug,提升测试效率和系统稳定性。欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
63 3
|
2月前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的全面指南在当今数字化时代,运维作为保障系统稳定性和效率的重要环节,其重要性不言而喻。本文将深入探讨如何构建一个高效的运维体系,从监控系统的搭建到自动化运维的实施,旨在为读者提供一套完整的解决方案。
本文详细介绍了高效运维体系的构建过程,包括监控系统的选择与部署、日志分析的方法、性能优化的策略以及自动化运维工具的应用。通过对这些关键环节的深入剖析,帮助运维人员提升系统的可靠性和响应速度,降低人工干预成本,实现业务的快速发展和稳定运行。
|
3月前
|
存储 弹性计算 运维
自动化监控和响应ECS系统事件
阿里云提供的ECS系统事件用于记录云资源信息,如实例启停、到期通知等。为实现自动化运维,如故障处理与动态调度,可使用云助手插件`ecs-tool-event`。该插件定时获取并转化ECS事件为日志存储,便于监控与响应,无需额外开发,适用于大规模集群管理。详情及示例可见链接文档。
|
3月前
|
存储 运维 监控
构建高效运维体系:从监控到自动化的全方位实践指南
在当今数字化时代,企业对运维(Operations)的需求日益增长。运维不仅仅是保持系统运行那么简单,它涉及到监控、日志管理、故障排除、性能优化和自动化等多个层面。本文将从实际操作的角度出发,详细探讨如何构建一个高效的运维体系。通过具体案例,我们将了解不同运维工具和方法的应用,以及它们是如何帮助企业提高生产效率和降低运营风险的。无论你是刚接触运维的新手,还是经验丰富的专家,这篇文章都将为你提供宝贵的参考和启示。
|
2月前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的实践之路
在当今信息技术飞速发展的时代,运维作为保障企业信息系统稳定运行的关键环节,其重要性日益凸显。本文将探讨如何通过构建高效的运维体系,实现从被动响应到主动预防的转变,以及如何利用自动化工具提升运维效率和质量。我们将从运维的基本概念出发,逐步深入到监控、自动化和安全管理等方面,为企业提供一套实用的运维优化方案。
82 0
|
3月前
|
存储 运维 监控
构建高效运维体系:从监控到自动化的全方位实践
在当今信息技术飞速发展的时代,运维作为保障信息系统稳定运行的关键环节,其重要性不言而喻。本文将围绕如何构建一个高效的运维体系进行深入探讨,内容涵盖从监控、日志分析到自动化运维工具的选择与应用,以及在实际工作中的经验和案例分享。通过本文的介绍,读者将能够了解到如何在复杂多变的技术环境中,确保系统的高可用性、高性能和安全性,为业务连续性提供坚实保障。