李老师云计算20级作业题参考

Posted WtcSky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了李老师云计算20级作业题参考相关的知识,希望对你有一定的参考价值。

索引

前言

持续更新,直到结束……

内容可能来自博主自己手搓、吸取同学的经验、网络上内容的整合等等,仅供参考,更多内容可以查看大三下速通指南专栏。

作业1:环境和可持续的角度的经济成本的比较分析

题目描述:

  1. (论述题) 作业1:假定有A互联网公司对3万家中小企业提供服务,所需的配置:每个季度的最后一个月需要100台主频3.5G、内存32G、硬盘1T、外网网速10M的计算机同时工作,运维人员2人,月工资6000元,机器运行电费每月150元;其他时段不需要IT资源工作。 请从环境和可持续的角度,对A公司使用传统模式和云计算模式进行经济成本的比较分析(提示:场地、网络、物理服务器、IT运维人员、部署周期、运行维护、工作负载模式、是否按峰值配备服务器、总体投入、资源利用率10个方面加以对比)。

参考答案:

从环境和可持续的角度考虑,云计算模式相比传统模式具有许多优势。下面是对传统模式和云计算模式在以下十个方面进行经济成本的比较分析:

  1. 场地成本

传统模式需要购买或租赁大量机房来放置物理服务器,而云计算模式可以通过云服务提供商的虚拟化技术来无需大量的场地。因此,云计算模式在场地成本方面具有优势。

  1. 网络成本

统模式需要建设专用的网络基础设施,包括网络线路、交换机、路由器等设备。云计算模式则可以通过公共云服务商提供的高速网络来满足网络需求,避免了建设和维护成本。因此,云计算模式在网络成本方面具有优势。

  1. 物理服务器成本

传统模式需要购买或租赁大量的物理服务器,而云计算模式可以通过云服务提供商的虚拟化技术来减少物理服务器的数量,避免了服务器硬件设备的购买、维护和更新成本。因此,云计算模式在物理服务器成本方面具有优势。

  1. IT运维人员成本

传统模式需要招聘和培训专业的IT运维人员来管理和维护物理服务器,而云计算模式可以通过云服务提供商提供的服务来减少IT运维人员的数量,避免了招聘、培训和薪资成本。因此,云计算模式在IT运维人员成本方面具有优势。

  1. 部署周期

传统模式需要花费较长的时间来购买、安装和配置物理服务器,而云计算模式可以通过自动化的部署工具来快速地创建和配置虚拟服务器,从而缩短了部署周期。因此,云计算模式在部署周期方面具有优势。

  1. 运行维护成本

传统模式需要定期维护和更新物理服务器,包括软件升级、硬件更换等,而云计算模式则由云服务提供商负责维护和更新虚拟服务器,无需额外的运行维护成本。因此,云计算模式在运行维护成本方面具有优势。

  1. 工作负载模式

传统模式需要根据峰值负载进行服务器规模的设计,而云计算模式可以根据实际需要动态地调整虚拟服务器的规模,根据负载情况自动伸缩,从而避免了闲置资源的浪费。因此,云计算模式在工作负载模式方面具有优势。

  1. 按峰值配备服务器成本

传统模式需要按照峰值负载进行服务器配备,因此在峰值期间可能会有大量闲置的资源浪费。而云计算模式可以根据实际需要动态调整虚拟服务器的规模,避免了闲置资源的浪费,因此在按峰值配备服务器成本方面具有优势。

  1. 总体投入成本

传统模式需要购买、维护和更新大量的物理服务器,并且需要招聘和培训专业的IT运维人员,因此总体投入成本较高。而云计算模式可以通过云服务提供商的服务来减少物理服务器的数量和IT运维人员的数量,从而降低总体投入成本。因此,云计算模式在总体投入成本方面具有优势。

  1. 资源利用率

传统模式由于服务器数量固定,因此资源利用率可能不高。而云计算模式可以根据实际需要动态调整虚拟服务器的规模,避免了闲置资源的浪费,从而提高了资源利用率。因此,云计算模式在资源利用率方面具有优势。

综上所述,云计算模式相比传统模式在环境和可持续的角度具有很多优势,包括场地成本、网络成本、物理服务器成本、IT运维人员成本、部署周期、运行维护成本、工作负载模式、按峰值配备服务器成本、总体投入成本和资源利用率等方面。因此,云计算模式是一种更加经济和可持续的选择。

作业2:参照Eclipse Mapreduc访问Hadoop文档,求解n个数的最大值

注意按理来说这个作业要完成实验一才能做,但是不知为何实验一的提交时间是晚于这个作业的(晚一个周),不知道是什么用意,可能是为了让我们沉淀一下,迎接审判。

完整的代码在最下面,**如果运行Hadoop的项目不把从机打开,可能会出现出现目录但没有结果文件的情况。**虽然是这么写的,但不一定要按照这个来,那些描述都是跑出来的可以看一下但不要较真……

题目描述:

  1. MapReduce介绍

    1.1 MapReduce编程模型(评分点1)

    1.2 MapReduce处理过程(评分点2)

  2. MapReduce求最大值处理过程

    2.1 分割过程(评分点3)

    2.2 Map排序与Combine过程(评分点4)

    2.3 Reduce排序与输出结果(评分点5)

  3. 基于Eclipse的MapReduce项目求解最大值

    3.1 Eclipse访问HDFS(评分点6)

    3.2 作业配置实现(评分点7)编写main函数,辅以充分的注释

    3.3 Map过程的实现(评分点8)Mapper类的局部变量、编写map函数,辅以充分的注释

    3.4 Reduce过程的实现(评分点9)Reducer类的局部变量、编写reduce函数,辅以充分的注释

  4. 测试(评分点10)给出测试数据,运行程序,得出计算结果。

参考答案:

1.1 MapReduce编程模型

MapReduce编程模型是一种分布式计算框架,其核心思想是将大规模数据集划分为许多小数据块,然后将这些小数据块分别交给多个计算节点进行处理,最终将结果进行合并。MapReduce编程模型包含两个阶段:Map阶段和Reduce阶段。在Map阶段,每个计算节点都会对自己所负责的数据块进行处理,将其映射为一系列键值对。在Reduce阶段,这些键值对会被按照键进行合并,并进行聚合操作。

1.2 MapReduce处理过程

MapReduce处理过程包括以下几个步骤:

  1. 输入分片:将输入数据分割为若干个数据块。
  2. Map处理:对每个数据块进行Map处理,并将结果输出为若干个键值对。
  3. Shuffle过程:对Map输出的键值对进行合并、排序、分组等操作,将同一键的值合并在一起,生成若干个键值对集合。
  4. Reduce处理:对每个键值对集合进行Reduce处理,生成若干个输出键值对。
  5. 输出:将Reduce输出的结果保存到输出文件中。
  6. MapReduce求最大值处理过程

2.1 分割过程

在这个问题中,我们需要将输入数据分割为若干个数据块,每个数据块包含若干个数值。由于我们需要求的是最大值,因此我们可以将数据块分割为大小相等的若干个子数据块,每个子数据块的大小为m。例如,如果输入数据为[1, 3, 5, 2, 4, 6, 7, 9, 8, 10],并且m=3,则我们可以将数据块分割为三个子数据块:[1, 3, 5], [2, 4, 6], [7, 9, 8, 10]。

2.2 Map排序与Combine过程

在Map阶段,每个计算节点都会对自己所负责的数据块进行处理,将其映射为一系列键值对。由于我们需要求最大值,因此我们可以将每个数据块中的最大值作为键,将输入数据块的编号作为值。例如,对于子数据块[1, 3, 5],其最大值为5,编号为0,因此我们可以将键值对(5, 0)输出。

在Map阶段的输出结果需要进行合并操作,以减少Reduce阶段的数据量。在本问题中,我们可以将Map输出的键值对按照键进行排序,并将同一键的值进行合并,生成若干个键值对集合。由于我们的键是数值,因此我们需要对键进行升序排序。

在对键值对进行排序的过程中,可以通过自定义比较器来指定排序方式。对于本问题中的键值对,我们可以通过编写一个比较器类来指定按照键的升序排序。下面是一个示例代码:

public class MaxValueComparator extends WritableComparator 
    protected MaxValueComparator() 
        super(IntWritable.class, true);
    

    @Override
    public int compare(WritableComparable a, WritableComparable b) 
        IntWritable int1 = (IntWritable) a;
        IntWritable int2 = (IntWritable) b;
        return int1.compareTo(int2);
    

在Map阶段的输出结果进行合并操作时,可以通过Combine过程来进一步减少数据量。Combine过程与Reduce过程相似,但是其运行在Map节点上,并且可以在Map节点上进行合并操作。在本问题中,我们可以使用Reduce过程作为Combine过程,将同一键的值进行合并,并输出合并后的键值对集合。

2.3 Reduce排序与输出结果

在Reduce阶段,对于每个键值对集合,我们可以对其进行Reduce操作,求出最大值。例如,对于键值对集合(5, [0, 2]),我们可以求出其对应的最大值10。对于本问题中的Reduce操作,我们可以编写一个Reducer类来实现。下面是一个示例代码:

public class MaxValueReducer extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable> 
    private IntWritable result = new IntWritable();

    @Override
    public void reduce(IntWritable key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException 
        int max = Integer.MIN_VALUE;
        for (IntWritable value : values) 
            max = Math.max(max, value.get());
        
        result.set(max);
        context.write(key, result);
    


在Reduce阶段的输出结果需要进行排序操作,以便将最大值排在最前面。在本问题中,我们可以使用与Map阶段类似的方式对输出结果进行排序,即使用一个比较器类来指定按照键的升序排序。下面是一个示例代码:

job.setSortComparatorClass(MaxValueComparator.class);
  1. 基于Eclipse的MapReduce项目求解最大值

3.1 Eclipse访问HDFS

在基于Eclipse的MapReduce项目中,我们需要使用HDFS作为输入和输出的数据源。因此,在编写代码之前,我们需要确保Hadoop和HDFS已经安装并运行在本地环境中。在Eclipse中,可以通过添加Hadoop库来访问HDFS。下面是一个示例代码:

Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://localhost:9000");
FileSystem fs = FileSystem.get(conf);
Path inputPath = new Path("/input");
Path outputPath = new Path("/output");
if (fs.exists(outputPath)) 
    fs.delete(outputPath, true);

3.2 作业配置实现

在配置MapReduce作业时,我们需要指定作业的输入、输出、Mapper类、Reducer类等信息。

Job job = Job.getInstance(conf, "max value");
job.setJarByClass(MaxValue.class);
job.setMapperClass(MaxValueMapper.class);
job.setCombinerClass(MaxValueReducer.class);
job.setReducerClass(MaxValueReducer.class);
job.setOutputKeyClass(IntWritable.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, inputPath);
FileOutputFormat.setOutputPath(job, outputPath);

在配置作业时,我们需要通过Job类的getInstance方法来获取一个作业实例,并指定作业的名称和运行配置。在本问题中,我们可以指定作业名称为"max value"。通过setJarByClass方法来指定运行作业的类,即MaxValue类。通过setMapperClass、setCombinerClass和setReducerClass方法来指定Mapper、Combine和Reducer类。通过setOutputKeyClass和setOutputValueClass方法来指定输出键和值的类型。最后,通过FileInputFormat和FileOutputFormat类的addInputPath和setOutputPath方法来指定作业的输入和输出路径。

public class MaxValue 
    public static void main(String[] args) throws Exception 
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://localhost:9000");
        FileSystem fs = FileSystem.get(conf);
        Path inputPath = new Path("/input");
        Path outputPath = new Path("/output");
        if (fs.exists(outputPath)) 
            fs.delete(outputPath, true);
        

        Job job = Job.getInstance(conf, "max value");
        job.setJarByClass(MaxValue.class);
        job.setMapperClass(MaxValueMapper.class);
        job.setCombinerClass(MaxValueReducer.class);
        job.setReducerClass(MaxValueReducer.class);
        job.setOutputKeyClass(IntWritable.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, inputPath);
        FileOutputFormat.setOutputPath(job, outputPath);

        boolean success = job.waitForCompletion(true);
        if (success) 
            System.out.println("Job completed successfully.");
        
    

在main函数中,我们首先创建一个Configuration对象,并设置默认文件系统为本地HDFS。然后,我们获取一个FileSystem对象,并指定输入和输出路径。在作业配置之后,我们通过调用waitForCompletion方法来等待作业运行完毕。最后,我们输出作业运行结果。如果作业运行成功,输出"Job completed successfully."。

3.3 Map过程的实现

public class MaxValueMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> 
    private final IntWritable one = new IntWritable(1);
    private IntWritable number = new IntWritable();

    @Override
    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException 
        String[] numbers = value.toString().split(",");
        for (String s : numbers) 
            number.set(Integer.parseInt(s));
            context.write(one, number);
        
    


在Mapper类中,我们首先声明两个局部变量:一个IntWritable类型的one变量,用于作为键;一个IntWritable类型的number变量,用于作为值。在map函数中,我们首先将输入的一行文本转换为一个字符串数组,然后遍历该数组。对于数组中的每个元素,我们将其转换为一个整数,并将其赋值给number变量。接下来,我们将one作为键,number作为值,通过调用Context对象的write方法写入上下文。这样,Map函数就将每个输入数值作为值输出,而将固定的键1与每个数值组合。

在Reducer类中,我们同样首先声明一个局部变量,用于保存输入值的最大值。在reduce函数中,对于每个键值对,我们将值转换为一个整数,并与当前最大值进行比较。如果值大于当前最大值,则将该值赋值给最大值变量。最后,我们通过调用Context对象的write方法将最大值写入上下文。

public static class MaxReducer extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable> 

    private IntWritable result = new IntWritable();

    public void reduce(IntWritable key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException 
        int max = Integer.MIN_VALUE;
        for (IntWritable val : values) 
            max = Math.max(max, val.get());
        
        result.set(max);
        context.write(key, result);
    


完整的代码如下:

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

public class MaxValue 

    public static class MaxValueMapper extends Mapper<LongWritable, Text, LongWritable, LongWritable> 

        private LongWritable lineNumber = new LongWritable();
        private LongWritable maxNumber = new LongWritable();

        @Override
        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException 

            String line = value.toString();
            String[] numbers = line.split(",");

            long max = Long.MIN_VALUE;
            for (String number : numbers) 
                long currentNumber = Long.parseLong(number.trim());
                if (currentNumber > max) 
                    max = currentNumber;
                
            

            lineNumber.set(key.get());
            maxNumber.set(max);

            context.write(lineNumber, maxNumber);
        
    

    public static class MaxValueReducer extends Reducer<LongWritable, LongWritable, LongWritable, LongWritable> 

        private LongWritable maxLineNumber = new LongWritable();
        private LongWritable maxValue = new LongWritable(Long.MIN_VALUE);

        @Override
        public void reduce(LongWritable key, Iterable<LongWritable> values, Context context)
                throws IOException, InterruptedException 

            long localMax = Long.MIN_VALUE;
            for (LongWritable value : values) 
                long currentValue = value.get();
                if (currentValue > localMax) 
                    localMax = currentValue;
                
            

            if (localMax > maxValue.get()) 
                maxValue.set(localMax);
                maxLineNumber.set(key.get());
            
        

        @Override
        protected void cleanup(Context context) throws IOException, InterruptedException 
            context.write(maxLineNumber, maxValue);
        
    

    public static void main(String[] args) throws Exception 
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Max Value");

        job.setJarByClass(MaxValue.class);
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);
        job.setMapperClass(MaxValueMapper.class);
        job.setReducerClass(MaxValueReducer.class);
        job.setMapOutputKeyClass(LongWritable.class);
        job.setMapOutputValueClass(LongWritable.class);
        job.setOutputKeyClass(LongWritable.class);
        job.setOutputValueClass(LongWritable.class);

        TextInputFormat.addInputPath(job, new Path(args[0]));
        TextOutputFormat.setOutputPath(job, new Path(args[1]));

        System.exit(job.waitForCompletion(true) ? 0 : 1);
    

创建一个输入文件,其中每行包含一个或多个用逗号分隔的整数,例如:

1, 2, 3, 4, 5
6, 7, 8, 9, 10
11, 12, 13, 14, 15

该文件中包含三行整数,每行包含五个整数。我们的程序将读取该文件,并返回其中的最大值,即15。

接下来,我们可以在Eclipse中创建一个MapReduce项目,并将上述代码复制到项目中的相应文件中。在项目中,我们需要在项目的src/main/resources目录下创建一个名为input的文件夹,并将上述测试数据文件复制到该文件夹中。

现在我们可以运行程序。首先,我们需要将项目打包成JAR文件。在Eclipse中,我们可以右键单击项目,选择Export,然后选择JAR文件并按照向导的指示进行操作。将生成的JAR文件上传到Hadoop集群中,并使用以下命令在Hadoop集群上运行程序:

hadoop jar maxvalue.jar input output

其中,maxvalue.jar是我们生成的JAR文件,input是输入文件夹的路径,output是输出文件夹的路径。运行程序后,Hadoop将在输出文件夹中生成一个名为part-r-00000的文件,其中包含计算出的最大值。我们可以使用以下命令查看该文件中的结果:

hadoop fs -cat output/part-r-00000

该命令将输出键值对(key-value),最终的答案是14 15

有效预警6要素:亿级调用量的阿里云弹性计算SRE实践

编者按:随着分布式系统和业务需求的飞速发展,监控告警在我们保障系统稳定性和事故快速恢复的全周期中都是至关重要的。9月3号,阿里云弹性计算管控SRE李成武老师(花名佐井),受「TakinTalks稳定性社区」邀请,在线分享日常预警治理工作的经验和心得,帮助大家实现精准的监控和告警,把问题扼杀在摇篮里,减少故障带来的业务损失。

以下是本次分享内容的文字整理。

如果事情有变坏的可能,不管这种可能性有多小,它总会发生。—— 墨菲定律

系统的稳定性离不开有效的预警机制,根据墨菲定律:可能出错的地方,一定会出错,我们没法准确预测系统会在什么时候在什么地方出错,但是却可以知道当系统出问题的时候,接口响应变慢、系统服务不可用、业务流量下跌或客户操作无法完成甚至有客户投诉。

为了对抗墨菲定律,我们必须未雨绸缪地在各种系统节点上配置预警信息,以免出问题的时候太过被动;同时为了追求问题发现率(更多的预警项、更不合理的阈值、更无关紧要的内容),我们有陷入了预警覆盖的悖论,最终导致了现在普遍的预警地狱现象。我们看下图,这是一个非常典型的正反馈增强回路,导致预警问题越来越多。

图:预警的正反馈增强回

更多的预警项会使问题变好吗?根据熵增定律,这一过程必然导致不可逆的破坏性,最终可能分不清哪些预警需要处理,甚至导致对预警的漠视。有没有办法解决这个问题?有,做负熵!从预警的各个环节循序渐进做减法,今天我们就聊聊预警环节的6要素。

在这6个预警要素中,有些是被公认且显而易见的,另外一些常被忽略导致预警地狱,本文综合了日常预警定义、通知、治理的经验和智慧,是预警治理的理想实践标准,关注保持良好的预警处理,持续解决系统隐患,促进系统稳定健康发展

01 准确:预警本身准确并正确通知

在大量被忽略的预警中,有很大一部分可以称为不准确,因为即使没有处理也不会发生什么实际问题,准确的第一个定义是预警达到了警告级别。无需处理的预警会导致“狼来了”效应,对预警越来越漠视,最终漏掉真正有需要处理的预警;曾经发现过这样的团队,几个小时报一次的预警没人看,只有到短时间高密度的预警通知才能引起注意,这样的团队对预警的免疫能力越来越强,也越来越危险。另外无效的预警通知还会导致不必须到资源浪费,比如:短信、电话费用等。所以,从现在开始,行动起来把无效预警干掉吧。

准确第二个定义是预警准确地通知到正确的接收人。不要以为预警通知的人越多就越可能被处理,实际不相关人收到告警更多是观望,实际上根本没人行动,因为这些无关的人没有动力也没有能力这么做。曾经遇到过一个case,与预警无关的同学通知需要预警应急的团队,看看你们系统是不是出力问题,虽然这种情况下无关通知起了作用,但对应该预警应急的团队是多么尴尬和可怕的事情啊。另外接收预警应急的同学也需要对预警通知做响应动作,一方面告知关注的同学,预警已经有人响应处理了,另一方面也未后面对预警的度量做数据准备。

总结下准确要素是把真正的预警信息通知到正确的接收人,这里面真正的预警正确的接收人缺少哪个都不应该发送;同时,这也是一次握手过程,接收人收到通知后要接手并准备处理。

02 适时:适时通知、适时应急

如果按预警的响应率,难道不是及时通知和响应更好,有些情况确实如此;但是别忘了我们来做负熵的,大部分情况我们做到适时就够了,避免过度紧张和恐慌。

首先,适时需要我们在不同时间段采用不同强度的通知渠道,比如夜间需要应急的预警,短信或IM很可能无法及时触达,需要用更强烈的通知方式,比如电话;但是在正常的工作时间,大家都是在线状态就没有这个必要。非常严重的预警,还是需要继续保持紧急的强通知以达到时效性,但是我们还是倡议非必须尽量不用。

其次,在应急上,对于没有及时响应的预警,可以升级成更强烈的通知渠道;同时也可以在处理人员上做升级,比如升级到主管、SRE等,以达到适时应急的目的。并不是每个预警都需要紧急处理的,比如:服务宕机,如果是线上许多机器中的一台,对业务流量不会造成影响,可以稍后再处理。

最后,适时要保障相同的预警不要短时间重复发送,避免淹没在预警炸弹中。一般情况是合并报警并做相关统计,然后根据预警分类做对应的抑制操作,或者让人工选择暂停一段时间的这类预警发送。当第一条预警被认领后,表示相关的应急处理已经启动,再推送相关预警更多是干扰,处理的效果可以通过监控观察,所以是不需要继续再报同样的预警的。

03 详尽:给出影响范围、上下文和诊断信息

收到告警后第一要事是确定问题然后采取对应的隔离或止血措施,如果告警内容太过简单,会让这个过程变成一个猜谜游戏,需要重新去现场,通过多种手段验证和推测,才能确定问题所在,这也是处理预警耗时最多的地方,而且这里很多是靠经验吃饭,新同学几乎很难插手。所以,在预警信息中给出影响范围和上下文和诊断信息,会上问题定位事半功倍。

首先,预警的影响范围是判断应急轻重缓急的重要指标。影响范围包括资源、业务、用户等维度:

  • 资源:单机、集群、相关依赖;
  • 用户:个别、部分还是全部客户;
  • 业务:核心业务、旁路业务、非核心业。

如果影响范围是个别情况,可以快速做隔离,比如把单个机器做隔离,摘除掉非核心链路或者单个客户做流控降级。相反,如果面积级别的,需要更采用更紧急响应机制,比如拉起更多的人处理:主管、SRE以及团队其它同学,甚至升级成故障级别。

其次,上下文信息会让定位事半功倍。上下文信息有助于判断错误的诊断,省去重新还原现场的麻烦。上下文信息包括:

◾ trace:给出预警问题的一条trace链路,相当于把现场还原;

◾ 日志:详细的错误日志link能定位到具体代码和当时的堆栈信息;

◾ 关联:关联的预警或变更,方便快速判断预警是不是由其它问题关联导致或因变更引起。

有了上下文信息,进一步排查的路径基本也确定了;否则需要去各种平台搜集信息、甚至需要重新恢复现成,而这些操作不仅耗时,还可能因为信息不全或时间流程导致无法得到需要的信息。

最后,预警中的诊断信息,甚至能直接给出定界原因,免去排查时间。问题的定位很多时候依赖处理人对业务的理解,对工具的使用,对平台的数据和曾经的经验。预警诊断就是把这些脑海中的流程经验通过规则+数据变成结果直接输出,诊断需要一定的系统能力建设才能实现,比如ECS内部采用下面的架构来支撑诊断:

1. 需要把不同渠道的预警信息统一接入,预警信息如果直接发送出去,就丢失了诊断环节,预警信息首先接入诊断层,才能实现后续诊断动作。

2. 需要有一定的信息收集能力,包括:各种meta信息(应用、数据库、api、人员、值班 …)、变更信息、运维工具、日志和其它预警信息等。

3. 需要有一定的信息整合能力,把预警和收集的信息做整合,结合诊断框架给出诊断结果。

04 恢复:隔离、止血、自愈

恢复是预警处理的第一要事,先要消除对系统、业务、客户的影响,然后才是排查问题。要素3(详尽:给出影响范围、上下文和诊断信息)业务为了定位到哪里出了问题,然后采取对应的恢复手动。

一般情况下,恢复需要执行一些动作,如果预警能更进一步,给出恢复操作,那将极大提升响应速度。

一般情况下恢复动作有以下执行路径:

◾ 故障自愈,根据预警判断影响并关联预制动作完成故障自愈。首先需要预警支持绑定call back动作,可以根据预警内容选择正确自愈操作;其次动作执行控制范围,避免自动执行动作带来二次故障。比如:我们可以检测到单机问题,把机器摘除掉。自愈需要判断好执行的范围和影响面,对有信心的动作才能自动执行。

◾ 止血动作的action,可以通过link或者chatops方式嵌入到预警内容中,点击相关action快速消除影响。比如:我们会在预警通知中,给出一些流控、重启、开关等动作,一键即可完成操作。

◾ 最佳实践、操作手册或者相关联系人,在没有止血action的时候,可以给出继续操作的指引,按照手册继续操作或联系能处理的人。

至此,我们通过4个要素的优化,完成了预警的整个应急过程,接下来2个要素讲关注预警的运营,通过高效、有效的运营,更进一步对预警进行治理。

05 覆盖:按模板自动覆盖

在故障复盘中,有不少问题没有及时发现的原因是缺少对应的监控。监控项是不可能覆盖全的,但是经验是可以积累传承的,通用、标准的预警适用大部分业务,可以通过模板方式做到更大范围的覆盖。

一类预警有这相似的监控项甚至差不多的阈值定义,这类标准的监控要能够在多个应用甚至业务上快速覆盖,通过巡检机制保障不会被遗漏。一般情况下预警的监控项分为基础监控和业务监控,业务重要等级不同,对监控和预警的定义也有差异。比如我们根据应用等级对监控也提出响应的等级,按照等级对监控通过模板进行覆盖,这样避免了忘记配置问题,同时新增资源或服务情况也做到自动覆盖。

通用的监控需要积累并模板化,这样能把经验传递下去,避免发送类似的问题。比如:之前兄弟团队出现过一个这样的故障。由于发布脚本问题,导致发布过程中从vip摘除的机器在发布完成后没有挂载上,当最后一个机器发布完成后,整个vip没有server导致业务不可用。我们通过复盘总结这样一个通用规则:vip中挂载的机器超过xx%被摘除后,出发一个预警,并应用到多个组织中,就避免了后续再发生类似的事情。

06 度量:通过数据统计做负熵

最后我们来聊聊预警的数据统计。管理大师德鲁克曾经说过:

你如果无法度量它,就无法管理它。(If you can’t measure it, you can’t manage it.) —— 彼得·德鲁克

度量是完成预警治理闭环的重要一环,其实我们这里是借助“精益”的思想,通过数据反馈发现问题,然后在问题上进行尝试,再回头看数据。

度量的数据可以包括以下几个方面:

◾ 预警的具体数据:用于分析后续分析改进、统计通知频率、统计预警量,比如:每个平均1天不超过3条,TOP人/团队/应用等红黑榜。

◾ 是否被标记无效:清理无效预警。

◾ 是否有人认领:认领率需要通过红黑榜通晒。

◾ 认领的时间:应急改进,故障类的可以参考 “1-5-10”(1分钟发现问题,5分钟定位,10分钟恢复)。

◾ 解决的时间:更好的完成 “1-5-10”。

◾ 预警工具的使用情况:改进工具的推荐准确性。

有了这些运营的数据,治理起来就有了抓手,持续的运营下去,才能让预警往更健康的方向演进。

总结

最后,结合一个阿里云弹性计算的内部实践,说明我们怎么结合6要素进行预警治理的。

我们在预警方面构建了一个统一的预警平台,把6要素通过工程方式融入到预警生命周期管理上。

首先我们收口了大部分的预警渠道,在内部我们有SLS、POP、ARMS、DAS、Promethues等多个预警源,这些预警会通知到预警网关而不是具体的人。预警网关会对这些数据进行解析、架构和诊断操作。

诊断环境我们把会输出影响面、根因和快恢工具,这部分是最复杂的,需要有一定的信息整合能力和诊断能力。首先我们会把预警信息与meta进行关联,meta是我们内部持续建设的基础数据,里面包含了,资源信息(机器、数据库、API、应用等等)、组织信息(组织架构、owner信息、值班信息)和策略信息(应急流程、升级策略、通知策略等);除此之外,针对预警内容我们还要做诊断影响面(影响客户、地域、资源、api等),同时保留上下文并抓取日志或trace链路,最后结合对预警内容的分析给出恢复工具。这些信息会通过模板引擎进行渲染,最终推送到具体人。

在诊断过程,如果我们发现预警需要升级,会自动升级预警基本并启动对应的应急流程,比如:识别重保客户,会启动alert流程进行应急。

最后,通过数据的量化,形成对应的红黑榜通晒,持续对不达标的指标进行治理。同时也会通过数据分析我们在治理流程上的不足,持续迭代,形成闭环。

原文链接

本文为阿里云原创内容,未经允许不得转载。

以上是关于李老师云计算20级作业题参考的主要内容,如果未能解决你的问题,请参考以下文章

边缘计算助力云游戏成为5G时代的杀手级应用

有效预警6要素:亿级调用量的阿里云弹性计算SRE实践

李老师云计算实验一:Hadoop伪分布式集群部署与Eclipse访问Hadoop进行单词计数统计

阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路

阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路

云计算--大数据IDC行业。