Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >7000 字 | 20 图 | 一文带你搭建一套 ELK Stack 日志平台

7000 字 | 20 图 | 一文带你搭建一套 ELK Stack 日志平台

作者头像
悟空聊架构
发布于 2022-05-13 09:00:24
发布于 2022-05-13 09:00:24
90700
代码可运行
举报
运行总次数:0
代码可运行

这是悟空的第 145 篇原创文章

官网:www.passjava.cn

你好,我是悟空呀~

前言

最近在折腾 ELK 日志平台,它是 Elastic 公司推出的一整套日志收集、分析和展示的解决方案。

专门实操了一波,这玩意看起来简单,但是里面的流程步骤还是很多的,而且遇到了很多坑。在此记录和总结下。

本文亮点:一步一图、带有实操案例、踩坑记录、与开发环境的日志结合,反映真实的日志场景。

日志收集平台有多种组合方式:

  • ELK Stack 方式:Elasticsearch + Logstash + Filebeat + Kibana,业界最常见的架构。
  • Elasticsearch + Logstash + Kafka + Kibana,用上了消息中间件,但里面也有很多坑,放到下一讲。

这次先讲解 ELK Stack 的方式,这种方式对我们的代码无侵入,核心思想就是收集磁盘的日志文件,然后导入到 Elasticsearch。

比如我们的应用系统通过 logback 把日志写入到磁盘文件,然后通过这一套组合的中间件就能把日志采集起来供我们查询使用了。

整体的架构图如下所示,

流程如下:

  • 先使用 Filebeat 把日志收集起来,然后把数据再传给 Logstash。
  • 通过 Logstash 强大的数据清洗功能。
  • 最终把数据写入到 Elasticsearch 中。
  • 并由 Kibana 进行可视化。

温馨提示:以下案例都在一台 ubuntu 虚拟机上完成,内存分配了 6G。

一、部署 Elasticsearch 数据库

获取 elasticsearch 镜像

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
docker pull elasticsearch:7.7.1

创建挂载目录

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir -p /data/elk/es/{config,data,logs}

赋予权限

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
chown -R 1000:1000 /data/elk/es

创建配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd /data/elk/es/config
touch elasticsearch.yml
-----------------------配置内容----------------------------------
cluster.name: "my-es"
network.host: 0.0.0.0
http.port: 9200

启动 elasticsearch 容器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
docker run -it  -d -p 9200:9200 -p 9300:9300 --name es -e ES_JAVA_OPTS="-Xms1g -Xmx1g" -e "discovery.type=single-node" --restart=always -v /data/elk/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /data/elk/es/data:/usr/share/elasticsearch/data -v /data/elk/es/logs:/usr/share/elasticsearch/logs elasticsearch:7.7.1

验证 elasticsearch 是否启动成功

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl http://localhost:9200

二、部署 Kibana 可视化工具

2.1 安装 Kibana

获取 kibana 镜像

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
docker pull kibana:7.7.1

获取elasticsearch容器 ip

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
docker inspect --format '{{ .NetworkSettings.IPAddress }}' es

结果:172.17.0.2

创建 kibana 配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir -p /data/elk/kibana/
vim /data/elk/kibana/kibana.yml

配置内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: ["http://172.17.0.2:9200"]
xpack.monitoring.ui.container.elasticsearch.enabled: true

2.2 运行 kibana

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name kibana -p 5601:5601 -v /data/elk/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:7.7.1

访问 http://192.168.56.10:5601。这个 IP 是服务器的 IP。Kibana 控制台的界面如下所示,打开 kibana 时,首页会提示让你选择加入一些测试数据,点击 try our sample data 按钮就可以了。

Kibana 界面上会提示你是否导入样例数据,选一个后,Kibana 会帮你自动导入,然后就可以进入到 Discover 窗口搜索日志了。

image-20220427161645270

三、部署 logstash 日志过滤、转换工具

3.1 安装 Java JDK

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install openjdk-8-jdk

修改 /etc/profile 文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sudo vim /etc/profile

添加如下的内容到你的 .profile 文件中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# JAVA
JAVA_HOME="/usr/lib/jdk/jdk-12"
PATH="$PATH:$JAVA_HOME/bin"

再在命令行中打入如下的命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
source /etc/profile

查看 java 是否配置成功

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
java -version

3.2 安装 logstash

下载 logstash 安装包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-7.7.1.tar.gz

解压安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
tar -xzvf logstash-7.7.1.tar.gz

要测试 Logstash 安装,请运行最基本的 Logstash 管道。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd logstash-7.7.1
bin/logstash -e 'input { stdin { } } output { stdout {} }'

等 Logstash 完成启动后,我们在 stdin 里输入以下文字,我们可以看到如下的输出:

当我们打入一行字符然后回车,那么我们马上可以在 stdout 上看到输出的信息。如果我们能看到这个输出,说明我们的 Logstash 的安装是成功的。

我们进入到 Logstash 安装目录,并修改 config/logstash.yml 文件。我们把 config.reload.automatic 设置为 true。

另外一种运行 Logstash 的方式,也是一种最为常见的运行方式,运行时指定 logstash 配置文件。

3.3 配置 logstash

Logstash 配置文件有两个必需元素,输入(inputs)和输出(ouputs),以及一个可选元素 filters。输入插件配置来源数据,过滤器插件在你指定时修改数据,输出插件将数据写入目标。

我们首先需要创建一个配置文件,配置内容如下图所示:

创建 kibana 配置文件 weblog.conf

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir -p /logstash-7.7.1/streamconf
vim /logstash-7.7.1/streamconf/weblog.conf

配置内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
input {
  tcp {
    port => 9900
  }
}
 
filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }
 
  mutate {
    convert => {
      "bytes" => "integer"
    }
  }
 
  geoip {
    source => "clientip"
  }
 
  useragent {
    source => "agent"
    target => "useragent"
  }
 
  date {
    match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  }
}
 
output {
  stdout { }
 
  elasticsearch {
    hosts => ["localhost:9200"]
  }
}

在上面,我们同时保留两个输出:stdout 及 elasticsearch。事实上,我们可以定义很多个的输出。stdout 输出对于我们初期的调试是非常有帮助的。等我们完善了所有的调试,我们可以把上面的 stdout 输出关掉。

等更新完这个配置文件后,我们在另外一个 console 中发送第一个 log:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
head -n 1 weblog-sample.log | nc localhost 9900

这个命令的意思:我们使用 nc 应用读取第一行数据,然后发送到 TCP 端口号 9900,并查看 console 的输出。

这里的 weblog-sample.log 为样例数据,内容如下,把它放到本地作为日志文件。

14.49.42.25 - - [12/May/2019:01:24:44 +0000] "GET /articles/ppp-over-ssh/ HTTP/1.1" 200 18586 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2b1) Gecko/20091014 Firefox/3.6b1 GTB5"

logstash 控制台打印出了 weblog-samle.log 中的内容:

这一次,我们打开 Kibana,执行命令,成功看到 es 中的这条记录。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET logstash/_search

四、部署 Filebeat 日志收集工具

4.1 安装 Filebeat

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.7.1-linux-x86_64.tar.gz
tar xzvf filebeat-7.7.1-linux-x86_64.tar.gz

请注意:由于 ELK 迭代比较快,我们可以把上面的版本 7.7.1 替换成我们需要的版本即可。我们先不要运行 Filebeat。

4.2 配置 Filebeat

我们在 Filebeat 的安装目录下,可以创建一个这样的 filebeat_apache.yml 文件,它的内容如下,首先先让 filebeat 直接将日志文件导入到 elasticsearch,来确认 filebeat 是否正常工作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /home/vagrant/logs/*.log

output.elasticsearch:
  hosts: ["192.168.56.10:9200"]

paths 对应你的日志文件夹路径,我配置的是这个:/home/vagrant/logs/*.log,之前配置成 /home/vagrant/logs 不能正常收集。另外这里可以放入多个日志路径。

4.3 测试 Filebeat

在使用时,你先要启动 Logstash,然后再启动 Filebeat。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bin/logstash -f weblog.conf

然后,再运行 Filebeat, -c 表示运行指定的配置文件,这里是 filebeat_apache.yml。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./filebeat -e -c filebeat_apache.yml

运行结果如下所示,一定要确认下控制台中是否打印了加载和监控了我们指定的日志。如下图所示,有三个日志文件被监控到了:error.log、info.log、debug.log

我们可以通过这个命令查看 filebeat 的日志是否导入成功了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl http://localhost:9200/_cat/indices?v

这个命令会查询 Elasticsearch 中所有的索引,如下图所示,filebeat-7.7.1-* 索引创建成功了。因为我没有配置索引的名字,所以这个索引的名字是默认的,。

在 kibana 中搜索日志,可以看到导入的 error 的日志了。不过我们先得在 kibana 中创建 filebeat 的索引(点击 create index pattern 按钮,然后输入 filebeat 关键字,添加这个索引),然后才能在 kibana 的 Discover 控制台查询日志。

创建查询的索引

搜索日志

4.4 Filebeat + Logstash

接下来我们配置 filebeat 收集日志后,输出到 logstash,然后由 logstash 转换数据后输出到 elasticsearch。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
filebeat.inputs:

- type: log
  enabled: true
  paths:
    - /home/vagrant/logs/*.log

output.logstash:
  hosts: ["localhost:9900"]

修改 logstash 配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim /logstash-7.7.1/streamconf/weblog.conf

配置了 input 为 beats,修改了 useragent

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
input {  
  beats {
    port => "9900"
  }
}
 
filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }
 
  mutate {
    convert => {
      "bytes" => "integer"
    }
  }
 
  geoip {
    source => "clientip"
  }
 
  useragent {
    source => "user_agent"
    target => "useragent"
  }
 
  date {
    match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  }
}
 
output {
  stdout {
    codec => dots {}
  }
 
  elasticsearch {
    hosts=>["192.168.56.10:9200"]
    index => "apache_elastic_example"
  }
}

然后重新启动 logstash 和 filebeat。有个问题,这次启动 filebeat 的时候,只监测到了一个 info.log 文件,而 error.log 和 debug.log 没有监测到,导致只有 info.log 导入到了 Elasticsearch 中。

filebeat 只监测到了 info.log 文件

logstash 输出结果如下,会有格式化后的日志:

我们在 Kibana dev tools 中可以看到索引 apache_elastic_example,说明索引创建成功,日志也导入到了 elasticsearch 中。

另外注意下 logstash 中的 grok 过滤器,指定的 message 的格式需要和自己的日志的格式相匹配,这样才能将我们的日志内容正确映射到 message 字段上。

例如我的 logback 的配置信息如下:

logback 配置

而我的 logstash 配置如下,和 logback 的 pettern 是一致的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grok {
    match => { "message" => "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n" }
  }

然后我们在 es 中就能看到日志文件中的信息了。如下图所示:

至此,Elasticsearch + Logstash + Kibana + Filebeat 部署成功,可以愉快地查询日志了~

后续升级方案:

  • 加上 Kafka
  • 加上 Grafana 监控
  • 链路追踪

五、遇到的问题和解决方案

5.1 拉取 kibana 镜像失败

failed to register layer: Error processing tar file(exit status 2): fatal error: runtime: out of memory

原因是 inodes 资源耗尽 , 清理一下即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
df -i
sudo find . -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl -s https://raw.githubusercontent.com/ZZROTDesign/docker-clean/v2.0.4/docker-clean |
sudo tee /usr/local/bin/docker-clean > /dev/null && \
sudo chmod +x /usr/local/bin/docker-clean
docker-clean

5.2 拉取 kibana 镜像失败

docker pull runtime: out of memory

增加虚拟机内存大小

5.3 Kibana 无法启动

"License information could not be obtained from Elasticsearch due to Error: No Living connections error"}

看下配置的 IP 地址是不是容器的 IP。


参考链接:

https://blog.csdn.net/UbuntuTouch/article/details/105973985

https://blog.csdn.net/UbuntuTouch/article/details/105979677

https://blog.csdn.net/yuemancanyang/article/details/122769308

https://elasticstack.blog.csdn.net/article/details/105922198

https://www.jianshu.com/p/8239d32f19e6

- END -

我是悟空,努力变强,变身超级赛亚人!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 悟空聊架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Docker 入门到实战教程(十二)ELK+Filebeat搭建日志分析系统
一般我们需要进行日志分析场景:直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。需要集中化的日志管理,所有服务器上的日志收集汇总。常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问。
小东啊
2020/07/23
4.7K1
Docker 入门到实战教程(十二)ELK+Filebeat搭建日志分析系统
在ELK+Filebeat搭建日志中心
当前环境 系统:centos7 docker 1.12.1 介绍 ElasticSearch Elasticsearch 是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。 Logstash Logstash 是一个具有实时渠道能力的数据收集引擎,主要用于日志的收集与解析,并将其存入 ElasticSearch中。 Kibana Kibana 是一款基于 Apache 开源协议,使用
Java架构
2018/05/04
1.4K0
在ELK+Filebeat搭建日志中心
Logstash、Filebeat安装与数据同步(+ES安装讲解)
如果你在你的 Terminal 中看到和我一样的输出,说明你的 Logstash 安装时成功的。
ha_lydms
2023/08/10
7260
Logstash、Filebeat安装与数据同步(+ES安装讲解)
ELK日志服务的搭建过程
① max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
:Darwin
2023/06/21
3250
基于Kafka+ELK搭建海量日志平台
早在传统的单体应用时代,查看日志大都通过SSH客户端登服务器去看,使用较多的命令就是 less 或者 tail。如果服务部署了好几台,就要分别登录到这几台机器上看,等到了分布式和微服务架构流行时代,一个从APP或H5发起的请求除了需要登陆服务器去排查日志,往往还会经过MQ和RPC调用远程到了别的主机继续处理,开发人员定位问题可能还需要根据TraceID或者业务唯一主键去跟踪服务的链路日志,基于传统SSH方式登陆主机查看日志的方式就像图中排查线路的工人一样困难,线上服务器几十上百之多,出了问题难以快速响应,因此需要高效、实时的日志存储和检索平台,ELK就提供这样一套解决方案。
王知无-import_bigdata
2019/07/29
9.2K0
基于Kafka+ELK搭建海量日志平台
一文轻松搞定ELK日志实时采集分析平台
ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件。
一行Java
2022/04/07
3.4K0
一文轻松搞定ELK日志实时采集分析平台
Linux安装ELK日志平台(7.5.1)
一般我们需要进行日志分析场景:直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大也就是日志量多而复杂的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。需要集中化的日志管理,所有服务器上的日志收集汇总。常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问。
子润先生
2021/07/07
1.8K1
ELK Stack日志中心搭建
本文主要目的是简化搭建ELK环境的步骤,使用Docker Compose部署ELK 7.1.1分布式集群的日志框架,只需要执行一个init.sh脚本即可搭建好一个ELK Stack日志中心。
茶半香初
2021/11/26
5800
ELK Stack日志中心搭建
7000 字 | 20 图 | 一文带你搭建一套 ELK Stack 日志平台
最近在折腾 ELK 日志平台,它是 Elastic 公司推出的一整套日志收集、分析和展示的解决方案。
用户1263954
2022/05/23
4110
7000 字 | 20 图 | 一文带你搭建一套 ELK Stack 日志平台
kubernetes Filebeat+ELK日志收集监控方案
接收来自filebeat的数据,根据其中的tags进行分类,再添加index进行分类,例如nginx-access-%{+YYYY.MM.dd},在kibana中会根据这个index获取日志。
kubernetes中文社区
2019/06/24
3.2K0
kubernetes  Filebeat+ELK日志收集监控方案
Docker安装ELK并实现JSON格式日志分析
ELK是elastic公司提供的一套完整的日志收集以及前端展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash和Kibana。
星哥玩云
2022/07/28
5500
Docker安装ELK并实现JSON格式日志分析
微服务架构中进行日志采集以及统一处理
微服务各个组件的相关实践会涉及到工具,本文将会介绍微服务日常开发的一些利器,这些工具帮助我们构建更加健壮的微服务系统,并帮助排查解决微服务系统中的问题与性能瓶颈等。
aoho求索
2020/11/13
1.5K0
微服务架构中进行日志采集以及统一处理
【ES三周年】 docker搭建elk初体验
这篇文章将着重于我对ELK的搭建初体验,基于部署和安装的方便,也为了巩固Docker相关的知识点的学习和熟练运行,尝试在使用Docker来搭建整个ELK系统。
猫老师的叶同学
2023/02/23
4800
ELK日志监控分析系统的探索与实践(一):利用Filebeat监控Springboot日志
由于公司项目较多,所部署服务产生的日志也较多,以往查看服务器日志只能通过xshell、putty等SSH工具分别连接每台服务器,然后进入到各个服务器,执行Linux命令查看日志,这样可能会带来以下问题:
大刚测试开发实战
2022/11/14
2.3K1
ELK日志监控分析系统的探索与实践(一):利用Filebeat监控Springboot日志
Docker 搭建 ELK 收集并展示 Tomcat 日志
前端展示 --> 索引搜索 <-- 日志提取及过滤 --> 日志缓存 <-- 日志收集 Kibana --> Elastash <-- Logstash --> redis <-- filebeat
星哥玩云
2022/07/28
5090
Docker 搭建 ELK 收集并展示 Tomcat 日志
搭建ELK日志分析平台并收集Nginx日志
一般我们需要进行日志分析场景:直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大也就是日志量多而复杂的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。需要集中化的日志管理,所有服务器上的日志收集汇总。常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问。
用户8826052
2021/07/12
1.4K0
使用 Docker Compose V2 快速搭建日志分析平台 ELK (Elasticsearch、Logstash 和 Kibana)
ELK的架构有多种,本篇分享使用的架构如图所示: Beats(Filebeat) -> -> Elasticsearch -> Kibana,目前生产环境一天几千万的日志,内存占用大概 10G 左右
易墨
2024/01/21
3.9K1
使用 Docker Compose V2 快速搭建日志分析平台 ELK (Elasticsearch、Logstash 和 Kibana)
快速搭建ELK7.5版本的日志分析系统--搭建篇
ELK是Elasticsearch、Logstash、Kibana的简称,这三者是核心套件,但并非全部
用户6641876
2020/02/19
1.7K0
elk7.15.1安装部署搭建
ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称(但是后期出现的Filebeat(beats中的一种)可以用来替代Logstash的数据收集功能,比较轻量级)。市面上也被成为Elastic Stack。
小陈运维
2021/10/22
1.9K0
Filebeat5+Kafka+ELK Docker搭建日志系统
纯粹是处于个人爱好,各种技术只要跟 Docker 搭边就倾爱它的 Docker 镜像版本。本文除了filebeat agent是二进制版本直接安装在应用机上,与docker无关,其他都是基于docker 镜像版本的集群安装。
曲水流觞
2019/11/05
9610
Filebeat5+Kafka+ELK Docker搭建日志系统
推荐阅读
相关推荐
Docker 入门到实战教程(十二)ELK+Filebeat搭建日志分析系统
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验