从零搭建Prometheus到Grafana告警推送

目录

一、Prometheus源码安装和动态更新配置

 二、Prometheus操作面板和常见配置

三、Prometheus常用监控组件exporter配置

3.1 exporter是什么

3.2 有哪些exporter

3.3 exporter怎么用

3.4 实战 node_exporter 

​3.5 其它exporter都怎么用

四、Promethus整合新版SpringBoot3.X应用监控

4.1 pom.xml引入依赖:

4.2 自定义健康检查

4.3 prometheus整合配置

五、可视化工具Grafana安装

5.1 什么是Grafana

5.2有哪些常用的功能

5.3快速安装部署

5.4 配置prometheus数据源

5.5 Grafana的用户和组织

 5.6Grafana explore

5.7Grafana最重要的dashboard

 5.8 Grafana高效导入仪表盘

八、Promethus的监控告警Alertmanager

8.1 什么是Alertmanager

8.2 Alertmanager安装

8.3 Alertmanager邮件告警配置步骤

​九、Grafana的Alert监控告警

9.1 Granfana的Alert和Alertmanager比对

9.2 Grafana的告警界面

9.3 Grafana新建推送通道

十、Grafana+钉钉群告警机器人

10.1 实战步骤

10.2 Grafana新建推送通道

10.3 面板Panel配置告警规则

10.4 错误信息跳转

10.5 结果验证


 本文主要介绍了使用Prometheus怎么监听应用服务和中间件。当使用Grafana时,怎么优雅快速的导入仪表盘以及设置阈值触发告警-将告警信息推送到邮件或者钉钉

一、Prometheus源码安装和动态更新配置

安装步骤:

配置go环境变量(Prometheus使用go语言开发)

#解压
tar -zxvf go1.17.6.linux-amd64.tar.gz

#配置环境变量 
echo "export PATH=$PATH:/usr/local/software/temp/go/bin" >> /etc/profile 

#立刻生效
source /etc/profile

#测试 go是否安装成功
go version

安装Prometheus:

#解压
tar -zxvf prometheus-2.43.0.linux-amd64.tar.gz

#重命名
mv prometheus-2.43.0.linux-amd64 prometheus

#进入目录启动
./prometheus --config.file=./prometheus.yml

#查看是否启动成功,默认端口9090
lsof -i:9090

#访问 prometheus ,阿里云网络安全组开放端口
  指标数据
  http://ip:9090/metrics
  图界面
  http://ip:9090/

动态更新:

prometheus里面经常需要修改配置,可以利用动态更新

启动时在参数中加入--web.enable-lifecycle   (该参数默认关闭)

#启动, &表示需要守护进程方式运行,不然退出终端则进程消失
./prometheus --config.file=./prometheus.yml --web.enable-lifecycle &

#动态更新配置
curl -X POST http://localhost:9090/-/reload

 二、Prometheus操作面板和常见配置

操作面板:

常见的配置:

#全局配置,默认,可以被覆盖
global:
  scrape_interval: 15s  #全局的抓取间隔
  scrape_timeout: 10s  #抓取超时时间
  evaluation_interval: 15s  #评估间隔

#告警配置
alerting:
  alertmanagers: #告警管理器
  - follow_redirects: true #是否启用重定向
    enable_http2: true #是否启用HTTP2
    scheme: http
    timeout: 10s
    api_version: v2 #指定Alertmanager的API版本,此处为v2
    static_configs: #告诉Prometheus哪些目标是静态的(即不会更改),如果有多个目标,则可以在targets中指定多个地址。
    - targets: []

#抓取配置
scrape_configs:
- job_name: prometheus #任务名称
  honor_timestamps: true #指标的时间戳应该由服务器提供,而不是客户端在发送指标时提供的时间戳
  scrape_interval: 15s #抓取任务的时间间隔,即每15秒抓取一次。
  scrape_timeout: 10s  #抓取任务的超时时间,单位为秒,即每个目标最多等待10秒钟
  metrics_path: /metrics  #抓取指标的路径
  scheme: http #指定抓取时使用的协议,默认为http
  follow_redirects: true  #是否启用重定向。在此处启用
  enable_http2: true  #是否启用HTTP2
  static_configs:
  - targets:
    - 120.xxx.xx.xxx:9090 #目标配置,告诉Prometheus哪些目标需要抓取,如果有多个目标,则可以在targets中指定多个地址
    
#此处抓取了一个名为prometheus的任务,每隔15秒抓取一次localhost:9090上的/metrics路径,超时时间为10秒

三、Prometheus常用监控组件exporter配置

3.1 exporter是什么

向Prometheus提供监控样本数据的程序都可以被称为一个Exporter
它是Prometheus的指标数据收集组件,负责从目标Jobs收集数据
并把收集到的数据转换为Prometheus支持的时序数据格式
只负责收集,并不向Server端发送数据,而是等待Prometheus Server 主动抓取

3.2 有哪些exporter

Prometheus社区以及其他团队开发了大量的Exporter,覆盖了许多不同类型的系统和服务
比如:Node Exporter、MySQL Exporter、Redis Exporter、MongoDB Exporter、Nginx Exporter...

3.3 exporter怎么用

在主机上安装了一个 Exporter程序,该程序对外暴露了一个用于获取当前监控样本数据的HTTP访问地址
Prometheus通过轮询的方式定时从这些Target中获取监控数据样本,并且存储在数据库当中

3.4 实战 node_exporter 

node_exporter  用于采集类UNIX内核的硬件以及系统指标,包括CPU、内存和磁盘

步骤:

#解压
tar -zxvf node_exporter-1.6.0.linux-amd64.tar.gz
 
#进到目录里面,启动
nohup ./node_exporter &

#确认端口
lsof -i:9100

通过浏览器访问 http://IP+9100/metrics可以查看到监控信息

 启动后exporter后,就需要将exporter的地址配置到prometheus.yml中

Prometheus服务器中添加被监控机器的配置 vim  prometheus.yml,   target的也可以写ip

  - job_name: 'agent-1'
    static_configs:
      - targets: ['120.xxx.7.xxx:9100']

 动态更新配置 curl -X POST http://localhost:9090/-/reload

查看Web UI界面的target和configuration是否有对应的数据 

 3.5 其它exporter都怎么用

一样的步骤:

对应的机器安装exporter
启动exporter 并监听对应的程序
访问对应的exporter的metric路径,看是否返回数据
Prometheus配置新的job
访问Prometheus查看target和configuration是否有数据

四、Promethus整合新版SpringBoot3.X应用监控

Promethus整合SpringBoot3.X应用监控

4.1 pom.xml引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

#暴露指定端点
management.endpoints.web.exposure.include=env,info,config,health

验证:访问 http://localhost:8080/actuator/prometheus, 查看详情

4.2 自定义健康检查

检查当前服务是否存活。继承AbstractHealthIndicator类,覆盖doHealthCheck方法,里面可以自定义up down。具体根据业务来设置即可

@Component
public class NanNanMQIndicator extends AbstractHealthIndicator {@Overrideprotected void doHealthCheck(Health.Builder builder) throws Exception {//对比两个不同方法builder.up().withDetail("MQ中间件","这个自带高可用");}
}


@Component
public class NanNanMQIndicator extends AbstractHealthIndicator {@Overrideprotected void doHealthCheck(Health.Builder builder) throws Exception {//对比两个不同方法builder.down().withDetail("DOWN MQ中间件","这个自带高可用");}
}

4.3 prometheus整合配置

 <!--整合prometheus--><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

编辑文件 prometheus.yml 15秒拉取一次应用服务数据

  - job_name: "springboot"
    scrape_interval: 15s
    scrape_timeout: 10s
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['120.xx.7.xx8080']

热更新配置 curl -X POST http://ip:9090/-/reload

 刚连接上,在promethus的界面就可以看到了== 界面不太好看==

五、可视化工具Grafana安装

5.1 什么是Grafana

它数据可视化工具,可以做数据监控和数据统计,带有告警功能。
面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件
比如热图、折线图、图表等多种展示方式

5.2有哪些常用的功能

报警:支持可视方式定义最重要指标的警报规则,Grafana将不断计算并发送通知,在数据达到阈值时进行告警

过滤器:过滤器允许动态创建新的键/值过滤器,这些过滤器将自动应用于使用该数据源的所有查询。
避免混淆各个组件主要的作用概念:
Exporter 数据生产者,采集需要监控的数据
Prometheus 普罗米修斯时序数据库,用来存储和查询的监控数据,从Exporter上拉取
Grafana 可视化工具仪表盘

5.3快速安装部署

 docker run -d -p 3000:3000 --name=nannanw-grafana grafana/grafana:8.1.5

 通过了浏览器访问http://IP+3000就能访问到登陆页面,默认用户名admin密码admin

5.4 配置prometheus数据源

 

 在这就可以看到设置后的数据源

5.5 Grafana的用户和组织

用户:

Grafana 里面用户有三种角色 admin,editor,viewer
admin 权限最高,可以执行任何操作,包括创建用户,新增 Datasource、DashBoard。
editor 角色不可以创建用户,不可以新增 Datasource,可以创建 DashBoard。
viewer 角色仅可以查看 DashBoard

新增用户后,可以分配角色

组织:
每个用户可以拥有多个 Organization,用户登录后可以在不同的 Organization 之间切换
不同的 Organization 之间完全不一样,包括 datasource,dashboard 等都不一样
创建一个 Organization 就相当于开了一个全新的视图,所有的 datasource,dashboard 等都要再重新开始创建

 5.6Grafana explore

explore和prometheus中的功能很相似

5.7Grafana最重要的dashboard

最重要 UI 界面 仪表盘,通过数据源定义好可视化的数据来源,Dashboard 来组织和管理数据可视化图表
仪表盘可以视为一组一个或多个面板组成的一个集合,来展示各种各样的面板。

第一步:

第二步:

再拖动到最下方点击'Use query'

然后就可以看到内存使用情况的图表展示

有没有发现,这样虽然可以展示出来,但是很麻烦?而且 样式没有那么炫酷,一个个调整起来也很费劲。

继续往下看~

 5.8 Grafana高效导入仪表盘

Grafana应用市场
地址:https://grafana.com/grafana/dashboards/

是Grafana社区和其他用户分享的可装载的仪表板和面板集合
Grafana模板使得共享可装载的仪表板变得容易,从而帮助用户减少了工作量,并促进了最佳设置和最佳配置的使用

举例:JVM相关监控仪表盘

点击  Copy ID to clipboard 

点击Import

在文本框中输入上一步的ID 点击load

然后就可以看到炫酷的仪表盘拉

根据上面的步骤,后续可以根据需要从应用市场中获取各个中间件的仪表数据进行展示

八、Promethus的监控告警Alertmanager

8.1 什么是Alertmanager

Prometheus的一个组件,用于定义和发送告警通知,内置多种第三方告警通知方式,同时还提供了对Webhook通知的支持
基于警报规则对规则产生的警报进行分组、抑制和路由,并把告警发送给合适的接收端,例如邮件、钉钉或Webhook

关键特点
分组:将详细的告警信息合并成一个通知,某些情况下,如由于系统宕机导致大量的告警被同时触发
抑制:当某一告警发出后,可以停止重复发送由此告警引发的其它告警的机制,避免告警轰炸
静默:根据标签对告警进行静默处理,如果接收到的告警符合静默的配置, Alertmanager则不会发送告警通知

8.2 Alertmanager安装

源码安装,默认端口9093
#解压
tar -zxvf alertmanager-0.24.0.linux-amd64.tar.gz
#启动
./alertmanager --config.file=alertmanager.yml
#守护进程方式启动
nohup ./alertmanager --config.file=alertmanager.yml &

访问 ip+port ,比如 http://112.74.xx.xxx:9093/#/alerts

8.3 Alertmanager邮件告警配置步骤

需求:部署的shop-project服务挂了,就触发邮件给开发人员

步骤:

1.Prometheus的rules.yaml编写告警规则,配置Prometheus,定义在哪些情况下被告警

Prometheus的rule.yaml(需要自己新建一个)配置文件

groups: # 告警规则组
- name: server-alarm
  rules: #规则,可以配置多个alert告警
  
  - alert: # 告警名称
    expr:  # 告警表达式,基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
    for:  # 评估等待时间,可选,用于表示只有当触发条件持续一段时间后才发送告警,在等待期间新产生告警 的状态为pending。
    labels: #自定义标签,允许用户指定要附加到告警上的一组附加标签。
      severity:  # 告警严重程度
    annotations: #用于指定一组附加信息,比如用于描述告警详细信息的文字等
      summary: # 告警摘要
      description: # 告警详细描述

  配置Prometheus关联Alertmanager地址和rules规则启用   vim prometheus.yml

 动态更新配置 curl -X POST http://localhost:9090/-/reload

在这也可以看到

当前状态:

2.配置Alertmanager 添加Email、钉钉或者短信接收程序,为告警通知指定目标和通知媒介

Alertmanager的alertmanager.yml配置文件

主要包含两个部分:路由(route) + 接收器(receivers)
告警信息会从配置中的顶级路由(route)进入路由树,根据路由规则将告警信息发送给相应的接收器

global:
  smtp_smarthost: 'smtp.126.com:25' # SMTP服务器地址和端口
  smtp_from: '131131777337@126.com' # 显示在邮件“发件人”字段中的地址
  smtp_auth_username: '131131777337@126.com' # STMP认证时使用的用户名
  smtp_auth_password: 'VBZGEVZXTIEJFOHW' # SMTP认证时使用的密码,不是密码
  smtp_require_tls: false # SMTP服务器是否需要TLS加密

route:
  receiver: 'email' # 发送告警通知的收件人,和下面的接受者名称匹配
  group_wait: 10s # 在发送前等待各个警报的时间
  group_interval: 30s # 相同警报名称的警报发送间隔
  repeat_interval: 10m # 重复发送警报的时间间隔
  group_by: ['alertname'] # 根据警报名分组告警接收者

# 告警接收者
receivers:
- name: 'email' # 接收者名称
  email_configs:
  - to: '71111222333@qq.com' # 接收告警邮件的收件人

邮箱准备:126.com

 然后重启Alertmanager

 #启动
./alertmanager --config.file=alertmanager.yml

#守护进程方式启动
nohup ./alertmanager --config.file=alertmanager.yml &

 验证步骤:

停止spring boot程序(停止其他服务都可以)

查看prometheus

这是挂了后的 

查看alertmanager

查看邮件

到这就可以收到邮件告警提示拉~

九、Grafana的Alert监控告警

Grafana也有告警功能,两个组件各有优缺点
Grafana更适合于小规模或简单的监控系统,而Alertmanager更适合于大规模或更复杂的告警处理场景


9.1 Granfana的Alert和Alertmanager比对

Grafana
优点:简单易用,Grafana的告警规则配置界面直观易懂,可以方便地设置告警的触发条件、持续时间和通知方式等。
缺点:不支持高级告警逻辑。Grafana只能识别基于简单算术或表达式的逻辑,无法支持更复杂的逻辑。


Alertmanager
优点:提供高级告警逻辑功能,支持许多常用的高级告警逻辑,如静默、抑制和聚合等。
支持多通道分发告警,支持将告警通知分发到多个通道,如电子邮件,短信等,能够满足不同场景下的需求。
缺点:复杂和难以部署,Alertmanager的配置比Grafana更复杂,需要深入了解监控系统和告警系统。
学习成本高,Alertmanager需要学习更多的知识和技能才能掌握

9.2 Grafana的告警界面

9.3 Grafana新建推送通道

十、Grafana+钉钉群告警机器人

需求:使用Grafana的alert告警模块,检测应用是否存活
配置自动告警机器人,如果应用宕机超过1分钟,推送到钉钉群

10.1 实战步骤

先进一个钉钉群,然后添加机器人

选择自定义

IP地址段设置的意义就是,设置后 只有这个地址的才能往钉钉中推送消息。也可以自定义关键词,AND的关系。当自定义的关键词命中的时候,也可以往钉钉群里推送消息。三个复选框是AND的关系。

复制地址

10.2 Grafana新建推送通道

10.3 面板Panel配置告警规则

需要选中想要检测的服务

然后再创建Alert

IS ABOVE 填1。最新值在1之下的数据.选择 IS BELOW才可以!0表示服务挂了。

save后点击Test Rule

10.4 错误信息跳转

配置钉钉错误信息详情跳转连接:
docker exec -u 0 -it nannanw-grafana /bin/bash

需要修改容器中grafana的defaults.ini 

 将配置中domain = localhost 改成grafana部署的服务器IP地址即可

保存后需要退出容器。然后再重启容器

重启容器

10.5 结果验证

关闭服务

查看grafana alerting

然后钉钉群就收到告警提示拉!

点击连接之后,就可以直接跳转到Grafana的详细告警页面

到这本文就更新结束拉~主要介绍prometheus怎么和应用服务关联 以及 其它相关exporter关联起来,包括grafana中如何优雅的导入仪表盘 以及2种告警的配置~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/868129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法mq 交互通用校验模块设计

背景 当前与算法交互均通过rocketMQ异步交互&#xff0c;绝大部分场景一条请求mq消息应对应一条返回mq&#xff0c;但由于各种原因&#xff08;消息积压、程序bug&#xff09;&#xff0c;可能会导致返回mq超时未返回或者消息丢失。工程侧针对一些重要场景 case by case的通过…

MySql数据库常用指令合集

MySql数据库常用指令合集 一、创建数据库db11.创建表 字段---表头 student_no,username,sex2.新增单条插入多条插入3.删除4.更新5.查询5.1.查询该表全部信息5.2.查询该表中username&#xff0c;并且要求名字为zhangsan性别女&#xff0c;还可以用&#xff08;or&#xff09; 6.…

卷积神经网络有哪些应用场景

卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;的应用场景非常广泛&#xff0c;尤其是在处理具有网格结构的数据&#xff08;如图像、视频&#xff09;时表现出色。以下是一些主要的应用场景&#xff1a; 1. 图像识别与分类 图像分类…

基础权限存储

一丶要求 建立用户组shengcan&#xff0c;其id为 2000建立用户组 caiwu&#xff0c;其id 为2001建立用户组 jishu&#xff0c;其id 为 2002建立目录/sc,此目录是 shengchan 部门的存储目录&#xff0c;只能被 shengchan 组的成员操作4.其他用户没有任何权限建立目录/cw,此目录…

GIT 使用相关技巧记录

目录 1、commit 用户信息变更 全局用户信息&#xff08;没有特殊配置的情况下默认直接用全局信息&#xff09; 特定仓库用户信息&#xff08;只针对于当前项目&#xff09; 方法一&#xff1a;修改config文件 方法二&#xff1a;命令方式 2、idea同一代码推向多个远端仓库…

Ubuntu编译 OSG

目录 一、安装步骤 二、配置 1、数据文件配置 2、OSG环境变量配置 一、安装步骤 在Ubuntu上安装OSG(OpenSceneGraph),你可以按照以下步骤操作: 打开终端,更新你的包管理器的包列表: sudo apt update 安装必要的依赖库 sudo apt install libglu1-mesa-dev freeglu…

Java -- 实现MD5加密/加盐

目录 1. 加密的引出2. MD5介绍3. 解决MD5不可解密方法4. 实现加密解密4.1 加密4.2 验证密码 1. 加密的引出 在MySQL数据库中&#xff0c;一般都需要把密码、身份证、电话号码等信息进行加密&#xff0c;以确保数据的安全性。如果使用明文来存储&#xff0c;当数据库被入侵的时…

8.做pwn题的大致流程

file <文件名> 判断是32还是64位&#xff0c;用对应工具分析&#xff08;比如ida&#xff0c;可以直接把文件拖到对应图标上&#xff09; ida中如果没找到main函数就找start函数从而找到main函数起始地址 两种分析方式&#xff1a; 静态分析ida 动态分析gdb 如果发现…

第七篇——攻谋篇:兵法第一原则——兵力原则,以多胜少

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 微观层面上&#xff0c;也有很多值得深度思考的问题 二、思路&方案 …

CV- 人工智能-深度学习基础知识

一, 深度学习基础知识 1,什么是深度学习?机器学习是实现人工智能的一种途径,深度学习是机器学习的一个子集,也就是说深度学习是实现机器学习的一种方法。2, 传统机器学习算术依赖人工设计特征,并进行特征提取,而深度学习方法不需要人工,而是依赖算法自动提取特征。深度…

一个SQL查询出表结构

select table_schema as “数据库”, table_name as “表名”, table_rows as “记录数”, truncate(data_length / 1024 / 1024,2) as “数据容量(MB)”, truncate(index_length / 1024 / 1024, 2) as “索引容量” from information_schema.tables where table_schema ‘数据…

MuLan:模仿人类画家的多对象图像生成

在图像生成领域&#xff0c;处理包含多个对象及其空间关系、相对大小、重叠和属性绑定的复杂提示时&#xff0c;现有的文本到图像模型仍面临挑战&#xff1a;当文本提示中包含多个对象&#xff0c;并且这些对象之间存在特定的空间关系时&#xff0c;现有模型往往难以准确地捕捉…

6.pwn Linux保护机制

保护机制 CANARY NX ASLR PIE RELRO 回顾 栈的作用为存储函数调用相关信息以及函数的局部变量 这些局部变量通常为数组或者输入的缓冲区(buf)。 而函数调用相关的信息&#xff0c;主要是返回地址和栈底指针(rbp) CANARY 看到程序里readfsqword&#xff08;0x28u&…

Spring 框架的基础知识

Spring 框架是由于软件开发的复杂性而创建的&#xff0c;Spring 使用的是基本的 JavaBean 来完成以前只可能由 EJB 完成的事。从简单性、可测性和松耦合性角度而言&#xff0c;绝大部分Java 应用都可以用 Spring。 1、控制反转&#xff08;Inversion of Control, IOC&#xff0…

差分进化算法

一、简介 差分进化&#xff08;DE&#xff09;是一种算法&#xff0c;通过创建一些随机个体&#xff0c;将它们与预定义的评估指标进行比较&#xff0c;并保留最好的个体&#xff0c;然后通过混合剩余个体的特征来创建新的个体&#xff0c;并重复这个过程来解决全局优化问题。…

嵌入式c语言4——类型修饰符

register&#xff0c;将变量保存在寄存器中&#xff0c;使得访问速度增加 const是常量&#xff0c;static是静态量&#xff0c;volatile是

从0-1实现一个前端脚手架

https://gitee.com/childe-jia/kfc-cli.git gitee完整地址 介绍 为什么需要脚手架&#xff1f; 脚手架本质就是一个工具&#xff0c;作用是能够让使用者专注于写代码&#xff0c;它可以让我们只用一个命令就生成一个已经配置好的项目&#xff0c;而不用我们再花时间去配置和安…

zabbix 与 grafana 对接

一.安装 grafana 1.初始化操作 初始化操作 systemctl disable --now firewalld setenforce 0 vim /etc/selinux/config SELINUXdisabled 2.上传数据包并安装 cd /opt grafana-enterprise-9.4.7-1.x86_64.rpm #上传软件包 yum localinstall -y grafana-enterprise-9.4.7-1…

Faster R-CNN 和 YOLO 对比

Faster R-CNN 和 YOLO 是两种常用的目标检测算法&#xff0c;它们在结构、性能和适用场景上有显著的区别。以下是两者的详细对比&#xff0c;包括各自的优缺点&#xff1a; Faster R-CNN 结构和原理&#xff1a; 两阶段检测器&#xff1a;Faster R-CNN 先通过区域提议网络&a…

Javascript常见数据结构和设计模式

在JavaScript中&#xff0c;常见的数据结构包括两大类&#xff1a;原始数据类型&#xff08;Primitive Types&#xff09;和对象类型&#xff08;Object Types&#xff09;。对象类型又可以进一步细分为多种内置对象、数组、函数等。下面是一些JavaScript中常见的数据结构&…