当前位置: 首页 > news >正文

任务13:使用MapReduce对天气数据进行ETL(获取各基站ID)

任务描述

知识点

  • 天气数据进行ETL

重  点

  • 掌握MapReduce程序的运行流程
  • 熟练编写MapReduce程序
  • 使用MapReduce进行ETL

内  容

  • 编写MapReduce程序
  • 编写Shell脚本,获取MapReduce程序的inputPath
  • 将生成的inputPath文件传入到Windows环境
  • 运行MapReduce程序对天气数据进行ETL处理

任务指导

1. 准备2000-2022年气象数据

(如在任务12中,按照手册已自行处理好2000-2022年的所有气象数据,也可跳过此步骤,使用自己处理好的数据文件即可,但需要在后续步骤中注意数据路径的问题)

先前按照任务12处理了2021-2022年数据,在后续气象预测部分任务需要2000-2022年的数据作为支持,所以现将处理后的(解压后)2000年-2022年的气象数据进行提供,可通过下述的URL下载地址进行下载

数据集路径:

格式:url/dataSet/systemLib/b3084be184684ee18f3b00b048bab0cc.zip,url参见实验窗口右侧菜单“实验资源下载”。

例如:https://staticfile.eec-cn.com/dataSet/systemLib/b3084be184684ee18f3b00b048bab0cc.zip

  • 在master机器的/home路径下载数据集
  • 解压数据集
  • 在/home/china_data目录中包含了2000-2022年,22年间的中国各个基站的气象数据

  • 在每个文件夹下均已将气象数据文件解压完成

使用MapReduce对天气数据进行预处理,并在数据文件中添加对应基站ID,并将原来字段间的分隔符改为使用逗号分隔,以便于大Hive中使用该数据集。

2. 使用MapReduce对数据进行ETL

当前在数据集中不包含基站编号字段,每个基站的编号体现在各个文件名的前5位,例如在“450010-99999-2000”文件中包含的是编号为“45001”的基站数据,所以需要将各个基站的编号添加到对应的数据文件中,并且在各个文件中每个字段之间的分隔符也是不一致的,所以也需要对数据进行清理,由于数据量较大,可以考虑使用MapReduce进行数据清理的工作。

  • 创建Maven项目:china_etl
  • 编写MapReduce程序
    • ChinaMapper:读取数据,对数据添加stn(基站ID)字段,并进行格式化处理
    • ChinaReducer:对处理后的数据进行输出
    • ChinaDriver:MapReduce程序的驱动类
  • 在master机器编写Shell脚本获取MapReduce程序的inputPath

  • 将生成的inputPath文件传入到Windows环境
  • 在Windows运行MapReduce程序
  • 程序运行完成,进入master机器查看结果

  • 数据格式说明:
基站编号时间温度露点温度气压风向风速云量1小时雨量6小时雨量
5999720221231212742501013370205-9999-9999

任务实现

1. 准备2000-2022年气象数据

(如在任务12中,按照手册已自行处理好2000-2022年的所有气象数据,也可跳过此步骤,使用自己处理好的数据文件即可,但需要在后续步骤中注意数据路径的问题)

先前按照任务12处理了2021-2022年数据,在后续气象预测部分任务需要2000-2022年的数据作为支持,所以现将处理后的(解压后)2000年-2022年的气象数据进行提供,可通过下述的URL下载地址进行下载

数据集路径:

格式:url/dataSet/systemLib/b3084be184684ee18f3b00b048bab0cc.zip,url参见实验窗口右侧菜单“实验资源下载”。

例如:https://staticfile.eec-cn.com/dataSet/systemLib/b3084be184684ee18f3b00b048bab0cc.zip

  • 在master机器的/home路径下载数据集
# cd /home
# wget https://staticfile.eec-cn.com/dataSet/systemLib/b3084be184684ee18f3b00b048bab0cc.zip
  • 解压数据集
# unzip /home/b3084be184684ee18f3b00b048bab0cc.zip
  • 在/home/china_data目录中包含了2000-2022年,22年间的中国各个基站的气象数据

  • 在每个文件夹下均已将气象数据文件解压完成

  • 将下载后的数据集上传至HDFS中
  • 将2000-2022年的所有气象数据上传至HDFS的/china目录中
# hadoop fs -mkdir /china
# hadoop fs -put /home/china_data/* /china

天气的格式如下:

NCDC天气的格式说明:

气象要素包括:气温、气压、露点、风向风速、云量、降水量等。

  • 例如:

  • 各字段的含义如下:
时间温度露点温度气压风向风速云量1小时雨量6小时雨量
202101010080-941028550601-9999-9999

当前在数据集中不包含基站编号字段,每个基站的编号体现在各个文件名的前5位,例如在“450010-99999-2000”文件中包含的是编号为“45001”的基站数据,所以需要将各个基站的编号添加到对应的数据文件中,并且在各个文件中每个字段之间的分隔符也是不一致的,所以也需要对数据进行清理,由于数据量较大,可以考虑使用MapReduce进行数据清理的工作。

2. 使用MapReduce对数据进行ETL

使用MapReduce对天气数据进行ETL流程如下:

  • 打开IDEA,如先前创建过项目,需点击File --> Close Project返回IDEA初始界面

  • 点击New Project新建项目

  • 创建Maven项目:china_etl

  • 打开File --> Settings,按照之前的方式配置Maven

  • 修改pom.xml文件,在标识位置填写<dependencies>标签中的内容,下载项目所需依赖

  • <dependencies>标签内容如下:
<dependencies>    <dependency>        <groupId>org.apache.hadoop</groupId>        <artifactId>hadoop-client</artifactId>        <version>2.9.2</version>    </dependency>
</dependencies>
  • 依赖下载完成后,将默认生成在src/main/java/com的Main类删除

  • 在src/main/java/com包下创建Mapper类:ChinaMapper.java

本次MapReduce任务的主要处理逻辑在Map函数中,在Map中获取当前正在处理的文件信息,通过文件信息获取相应的文件名,然后获取到文件名的前五位,前五位则是每个基站对应的基站编号,然后获取到数据文件中的每条数据并进行分割,分割后根据索引获取所需的数据,最后通过","对数据进行分隔,作为每个字段数据的新分隔符,根据所需重新将数据进行拼接

package com;import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;public class ChinaMapper extends Mapper<LongWritable, Text,Text, NullWritable> {@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//         获取当前map正在处理的文件信息InputSplit inputSplit = (InputSplit) context.getInputSplit();
//         获取文件名,例如:当前获取到“450010-99999-2000”String fileName = inputSplit.toString().split("/")[5];NullWritable val = NullWritable.get();
//        取出基站编号,例如:“45001”String stn = fileName.substring(0,5);
//     System.out.println(stn);/**     获取所需字段year=[]   #年month=[]  #月day=[]    #日hour=[]   #时间temp=[]   #温度dew_point_temp=[]  #露点温度pressure=[]        #气压wind_direction=[]   #风向wind_speed=[]       #风速clouds=[]          #云量precipitation_1=[]   #1小时降水量precipitation_6=[]   #6小时降水量
*/
//     获取输入的每一条数据String values = value.toString();
//     通过分隔符进行分割String[] lines = values.split("\\s+");String year = lines[0];String month = lines[1];String day = lines[2];String hour = lines[3];String temp = lines[4];String dew_point_temp = lines[5];String pressure = lines[6];String wind_direction = lines[7];String wind_speed = lines[8];String cloud=lines[9];String precipitation_1 = lines[10];String precipitation_6 = lines[11];
//     使用“,”对每条数据进行拼接,每条数据的分隔符设置为","String line = stn+","+year+","+month+","+day+","+hour+","+temp+","+dew_point_temp+","+pressure+","+wind_direction+","+wind_speed+","+cloud+","+precipitation_1+","+precipitation_6;System.out.println(line);
//     每条数据作为key进行输出context.write(new Text(line),val);}
}
  • 在src/main/java/com包下创建Reducer类:ChinaReducer.java
package com;import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;public class ChinaReducer extends Reducer<Text,NullWritable,Text,NullWritable> {@Overrideprotected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {NullWritable val = NullWritable.get();// 获取keyText outLine = key;context.write(outLine,val);}
}
  • 在src/main/java/com包下创建Driver类: ChinaDriver.java
package com;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;public class ChinaDriver {public static void main(String[] args) {Configuration conf = new Configuration();Job job = null;try {// 读取filename文件内容获取inputpathBufferedReader br = new BufferedReader(new FileReader("C:\\installed\\filename.txt"));String line = null;ArrayList list = new ArrayList();while((line=br.readLine())!=null){list.add(line);}Path[] inputPath = new Path[list.size()];for(int i = 0;i< inputPath.length;i++){inputPath[i] = new Path(list.get(i).toString());System.out.println(inputPath[i]);}job = Job.getInstance(conf);job.setJarByClass(ChinaDriver.class);job.setJobName("ChinaDriver");
//         设置Mapper类job.setMapperClass(ChinaMapper.class);
//         设置Reducer类job.setReducerClass(ChinaReducer.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(NullWritable.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(NullWritable.class);
//         设置输入路径FileInputFormat.setInputPaths(job, inputPath);
//         设置输出路径FileOutputFormat.setOutputPath(job, new Path("hdfs://master:9000/china_all/"));System.exit(job.waitForCompletion(true) ? 0 : 1);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}
}
  • 编写完成后,进入master机器

由于本次MapRedcue任务需要处理2000-2022年的数据,每个年份的数据都保存在一个以年份命名的文件夹下,所以MapReduce需要读取22个文件夹下的所有数据,因此在运行MapReduce程序前,需要编写一个Shell脚本以生成MapReduce的inputPath文件,在该文件中包含所有需要处理的数据路径(该操作类似任务12中的generate_input_list.sh脚本

  • 在master机器的/home/shell目录下,编写getHDFSfile.sh脚本,以生成MapReduce的inputPath文件
# vim /home/shell/getHDFSfile.sh
  • 脚本内容如下:
#/bin/bash
rm -rf /home/filename.txt
# file = echo `hdfs dfs -ls /china | awk -F ' ' '{print $8}'`
for line in `hdfs dfs -ls /china | awk -F ' ' '{print $8}'`
dofilename="hdfs://master:9000$line"echo -e "$filename" >> /home/filename.txt
done
  • 为Shell脚本赋予执行权限
# chmod u+x /home/shell/getHDFSfile.sh
  • 运行Shell脚本,生成inputPath
# /home/shell/getHDFSfile.sh
  • 脚本运行完成,在/home目录下会生成一个filename.txt文件,在文件中包含所有需要处理的路径信息
  • 查看/home/filename.txt文件
# cat /home/filename.txt 

  • filename.txt文件生成后,将其通过filezilla工具传入到Windows环境的C:\installed目录
  • 进入Windows环境,打开filezilla工具,filezilla需要配置master的主机名(IP地址)、用户名、密码以及端口;

  • 可通过右侧工具栏,获取master机器的相关信息并将其进行填入

  • 配置完成后,点击快速连接master机器
  • 在左侧拦中是本地Windows环境的文件管理器,右侧是连接的远程Linux(master)机器文件管理器

  • 在Windows文件管理器,进入C:\installed目录,在右侧master机器中进入/home目录,找到生成的filename.txt文件,将其从master机器中拖拽到Windows机器

  • 右键ChinaDriver,点击Run 'ChinaDriver.main()'运行MapReduce程序

  • 控制台显示数据

进入master机器,查看运行结果最后5行数据:

# hadoop fs -cat /china_all/* | tail -5

数据格式说明:

基站编号时间温度露点温度气压风向风速云量1小时雨量6小时雨量
5999720221231212742501013370205-9999-9999

上一个任务下一个任务

相关文章:

任务13:使用MapReduce对天气数据进行ETL(获取各基站ID)

任务描述 知识点&#xff1a; 天气数据进行ETL 重 点&#xff1a; 掌握MapReduce程序的运行流程熟练编写MapReduce程序使用MapReduce进行ETL 内 容&#xff1a; 编写MapReduce程序编写Shell脚本&#xff0c;获取MapReduce程序的inputPath将生成的inputPath文件传入到Wi…...

@Controller层自定义注解拦截request请求校验

一、背景 笔者工作中遇到一个需求&#xff0c;需要开发一个注解&#xff0c;放在controller层的类或者方法上&#xff0c;用以校验请求参数中(不管是url还是body体内&#xff0c;都要检查&#xff0c;有token参数&#xff0c;且符合校验规则就放行)是否传了一个token的参数&am…...

Ceph集群修改主机名

修改主机名 #修改主机名 rootlk02--test:~# hostnamectl set-hostname lk02--test01 #修改hosts rootlk02--test:~# vi /etc/hosts #修改ceph.conf rootlk02--test:~# vi /etc/ceph/ceph.conf rootlk02--test:~# cat /etc/ceph/ceph.conf |grep mon mon host [v2:192.168.3.1…...

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日&#xff0c;玖章算术旗下NineData 云原生智能数据管理平台 (V1.0&#xff09;正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试&#xff0c;并获得阿里云颁发的产品生态集成认证。 测试结果表明&#xff0c;玖章算术旗下NineData数据管理平台 (V1.0&#xff…...

(实战)oracle静默安装runInstaller数据库软件 --参数说明+举例

安装数据库软件 su - oracle cd database/ export LANGen_US export LANGen_US.UTF-8 ./runInstaller 进行安装 yum install -y binutils-* libXp* compat-libstdc-33-* elfutils-libelf-* elfutils-libelf-devel-* gcc-* gcc-c-* glibc-* glibc-common-* glibc-devel-* g…...

利用Python的csv(CSV)库读取csv文件并取出某个单元格的内容的学习过程

csv库在python3中是自带的。 利用它可以方便的进行csv文件内容的读取。 注意&#xff1a;要以gbk的编码形式打开&#xff0c;因为WPS的csv文件默认是gbk编码&#xff0c;而不是utf-8。 01-读取表头并在打印每一行内容时一并输出表头 表头为第1行&#xff0c;现在要读取并打…...

Http三种常见状态码的区别(401、403、500)

一、解释 401 Unauthorized&#xff08;未经授权&#xff09;&#xff1a;表示请求需要进行身份验证&#xff0c;但客户端未提供有效的身份验证凭据。通常&#xff0c;当用户尝试访问需要身份验证的资源时&#xff0c;服务器会返回401状态码&#xff0c;以提示客户端提供有效的…...

分布式锁实现用户锁

用户锁的作用 秒杀、支付等场景&#xff0c;用户频繁点击按钮&#xff0c;会造成同一时刻调用多次接口【第一次请求接口还没响应数据&#xff0c;用户又进行了第二次请求】&#xff0c;造成数据异常和网络拥堵。添加用户锁&#xff0c;在用户第二次点击按钮时&#xff0c;拦击用…...

R语言【paleobioDB】——pbdb_subtaxa():统计指定类群下的子类群数量

Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新&#xff0c;该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后&#xff0c;执行本地安装。 Usage pbdb_subtaxa (data, do.plot, col) Arguments…...

3.4 在开发中使用设计模式

现在&#xff0c;我们应该对设计模式的本质以及它们的组织方式有了初步的认识&#xff0c;并且能够理解ROPES过程在整体设计中的作用。通过之前章节对“体系结构”及其五个视图的探讨&#xff0c;我们打下了坚实的基础。初步了解了UML的基本构建模块后&#xff0c;我们现在可以…...

docker搭建SSH镜像、systemctl镜像、nginx镜像、tomcat镜像

目录 一、SSH镜像 二、systemctl镜像 三、nginx镜像 四、tomcat镜像 五、mysql镜像 一、SSH镜像 1、开启ip转发功能 vim /etc/sysctl.conf net.ipv4.ip_forward 1sysctl -psystemctl restart docker 2、 cd /opt/sshd/vim Dockerfile 3、生成镜像 4、启动容器并修改ro…...

[linux] git clone一个repo,包括它的子模块submodule

How do I "git clone" a repo, including its submodules? - Stack Overflow git clone git://github.com/foo/bar.git cd bar git submodule update --init --recursive...

K8S中使用helm安装MinIO

注意事项 使用helm部署MinIO分为两部分 helm部署MinIO operator&#xff0c;用来管理tenant&#xff08;K8S集群中只能部署一个&#xff09;helm部署MinIO tenant&#xff0c;真实的MinIO Cluster&#xff08;K8S集群中可以部署多个&#xff09; 使用helm部署到K8S集群&…...

寒假刷题第六天

PTA甲级 1030 Travel Plan 迪杰斯特拉 #include<iostream> #include<vector> #include<cstring>using namespace std;const int N 510 , INF 0x3f3f3f3f3f; int n , m , s , d; int g[N][N] , cost[N][N] , dist[N] , min_cost[N]; bool st[N]; int pat…...

深度学习笔记(七)——基于Iris/MNIST数据集构建基础的分类网络算法实战

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解&#xff0c;如有遗漏或错误&#xff0c;欢迎评论或私信指正。 截图和程序部分引用自北京大学机器学习公开课 认识网络的构建结构 在神经网络的构建过程中&#xff0c;都避不开以下几个步骤&#xff1a; 导入网络和依…...

Windows启动MongoDB服务报错(错误 1053:服务没有及时响应启动或控制请求)

问题描述&#xff1a;修改MongoDB服务bin目录下的mongod.cfg&#xff0c;然后在任务管理器找到MongoDB服务-->右键-->点击【开始】&#xff0c;启动失败无提示&#xff1a; 右键点击任务管理器的MongoDB服务-->点击【打开服务】&#xff0c;跳转到服务页面-->找到M…...

Android Framework 常见解决方案(25-2)定制CPUSET解决方案-system修改及编译部分调整

1 原理说明 这个方案有如下基本需求&#xff1a; 构建自定义CPUSET&#xff0c;/dev/cpuset中包含一个全新的cpuset分组。且可以通过set_cpuset_policy和set_sched_policy接口可以设置自定义CPUSET。开机启动后可以通过zygote判定来对特定的应用进程设置CPUSET&#xff0c;并…...

OpenAI推出GPT商店和ChatGPT Team服务

&#x1f989; AI新闻 &#x1f680; OpenAI推出GPT商店和ChatGPT Team服务 摘要&#xff1a;OpenAI正式推出了其GPT商店和ChatGPT Team服务。用户已经创建了超过300万个ChatGPT自定义版本&#xff0c;并分享给其他人使用。GPT商店集结了用户为各种任务创建的定制化ChatGPT&a…...

3D建模素材分层渲染怎么操作?

在3D建模素材分层渲染过程中&#xff0c;需要将场景中的元素分到不同的层里&#xff0c;然后分别进行渲染。以下是一个简单的方法&#xff1a; 1、打开要渲染的3D建模素材。 2、在场景中选择要分层的元素&#xff0c;然后在软件的图层面板中新建图层&#xff0c;将元素拖拽到新…...

SAICP(模拟退火迭代最近点)的实现

SAICP(模拟退火迭代最近点)的实现 注: 本系列所有文章在github开源, 也是我个人的学习笔记, 欢迎大家去star以及fork, 感谢! 仓库地址: pointcloud-processing-visualization 总结一下上周的学习情况 ICP会存在局部最小值的问题, 这个问题可能即使是没有实际遇到过, 也或多…...

Chandra效果实测:100轮连续中文对话稳定性与上下文保持能力验证

Chandra效果实测&#xff1a;100轮连续中文对话稳定性与上下文保持能力验证 测试背景说明&#xff1a;本次测试基于CSDN星图平台的Chandra镜像&#xff0c;在标准配置环境下进行100轮连续中文对话&#xff0c;全面评估其长时间运行的稳定性、上下文理解能力和响应表现。 1. 测试…...

市场知名的光伏项目品牌找哪家

这两年不少做企业的、建农村自建房的业主都盯上了光伏项目——发了电自己用&#xff0c;余电还能卖&#xff0c;长期收益稳定&#xff0c;不少人靠着光伏每年多赚几万甚至几十万。但我接触过至少几十个踩坑的业主&#xff1a;要么找了小品牌装完就跑路&#xff0c;发电量比承诺…...

基于SpringBoot + Vue的定制化设计服务平台

文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言 &#x1f49b;博主介绍&#…...

机器学习04——numpy

1、numpy介绍Numpy&#xff08;Numerical Python&#xff09;是一个开源的Python科学计算库&#xff0c;用于快速处理任意维度的数组。Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务&#xff0c;使用Numpy比直接使用Python要简洁的多。Numpy使用ndarray对象来处理多维…...

搞电机控制的兄弟应该都懂,无感算法里磁链观测器+PLL锁相环的组合有多香。今天直接上干货,聊聊非线性磁链观测器的实现套路和实操中那些让你少掉几根头发的技巧

永磁同步电机非线性磁链无感算法、Flux观测器锁相环PLL仿真模型 flux&#xff1a;计算电机磁链&#xff0c;目的为了使得估计的磁链收敛于实际磁链&#xff1b; pll&#xff1a;通过估计磁链计算经过pi调节后使得估计角度跟踪实际角度 模型描述及资料&#xff1a; &#xff08;…...

时间放大器:从亚稳态到数字训练式的硬件实现解析

1. 时间放大器的核心价值与应用场景 时间放大器&#xff08;Time Amplifier&#xff09;这个名词听起来有点科幻&#xff0c;但它的原理其实非常接地气。想象一下你用两根手指同时按下钢琴的两个琴键&#xff0c;如果两次按键的时间差只有几毫秒&#xff0c;普通人耳朵可能分辨…...

车载测试CAPL编程实战:结构(Struct)在车辆信号解析中的应用

1. 为什么车载测试需要结构&#xff08;Struct&#xff09;&#xff1f; 在车载测试领域&#xff0c;我们每天要处理海量的车辆信号数据。想象一下&#xff0c;一辆普通家用车的CAN总线上&#xff0c;每秒可能产生上千条报文&#xff0c;每条报文又包含多个信号值。比如发动机转…...

企业财务自动化全场景落地,从入门到精通的完整指南 —— 2026企业级智能体选型与实战路径

在2026年的数字化深水区&#xff0c;企业财务管理正经历从“信息化”向“原生智能化”的跨代跃迁。 随着金税四期的全场景覆盖与数据要素资产化的推进&#xff0c;财务部门已不再满足于基础的流程自动化。 从“钱、票、账、税、资”的碎片化处理&#xff0c;到构建全链路闭环的…...

《深入理解Mybatis原理》MyBatis数据源与连接池详解

在技术领域&#xff0c;我们常常被那些闪耀的、可见的成果所吸引。今天&#xff0c;这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力&#xff0c;让我们得以一窥未来的轮廓。然而&#xff0c;作为在企业一线构建、部署和维护复杂系统的实践者&#xff0c;我们深知…...

2026年企业APM应用性能观测工具选型指南:四大主流方案深度对比

2026年企业APM应用性能观测工具选型指南&#xff1a;四大主流方案深度对比 2026年&#xff0c;企业数字化转型进入云原生深水区&#xff0c;微服务、分布式架构已成为中大型企业IT系统的标配&#xff0c;同时AI Agent与大模型技术正在深度重构运维体系&#xff0c;可观测性已从…...