使用 Logstash 及 enrich processor 实现数据丰富自动化

在我之前的文章:

通过上面的两篇文章的介绍,我们应该充分掌握了如何使用 enrich processor 来丰富数据了。特别是在上面的第二篇文章中,我们需要使用手动来一个一个地通过 Kibana 的界面来写入数据。我们感觉还是比较麻烦。如果我们能够实现自动化来完成整个的操作,那将是非常好的。在今天的文章中,我们将结合 enrich processor 和 Logstash 来实现数据的丰富自动化。我们可以利用 Linux 所提供的脚本来完成数据摄入的自动化。

在一下的展示中,我将使用如下的架构来进行展示:

数据描述

在进行我们的练习之前,我们下载所需要的数据及相关文档:

bash 复制代码
git clone https://github.com/evermight/elasticsearch-ingest
markdown 复制代码
1.  arallels@ubuntu2004:~/data/elasticsearch-ingest/part-3$ pwd
2.  /home/parallels/data/elasticsearch-ingest/part-3
3.  parallels@ubuntu2004:~/data/elasticsearch-ingest/part-3$ tree -L 3
4.  .
5.  ├── 01-zip_geo.sh
6.  ├── 02-customer.sh
7.  ├── 03-product.sh
8.  ├── 04-order_item.sh
9.  ├── 05-order.sh
10.  ├── data
11.  │   ├── customer
12.  │   │   ├── data.csv
13.  │   │   └── readme.txt
14.  │   ├── mysql
15.  │   │   ├── load.sql
16.  │   │   └── readme.md
17.  │   ├── order
18.  │   │   ├── data.csv
19.  │   │   └── data.xlsx
20.  │   ├── order_item
21.  │   │   ├── data.csv
22.  │   │   └── data.xlsx
23.  │   ├── product
24.  │   │   └── data.csv
25.  │   └── zip_geo
26.  │       ├── data.csv
27.  │       └── data.xlsx
28.  ├── env.sample
29.  ├── logstash
30.  │   ├── customer.conf
31.  │   ├── order.conf
32.  │   ├── order_item.conf
33.  │   ├── product.conf
34.  │   └── zip_geo.conf
35.  ├── mapping
36.  │   ├── customer.json
37.  │   ├── order.json
38.  │   └── zip_geo.json
39.  ├── part-3.pdf
40.  ├── part-3.pptx
41.  ├── pipeline
42.  │   ├── customer.json
43.  │   ├── order_item.json
44.  │   └── order.json
45.  ├── policy
46.  │   ├── customer.json
47.  │   ├── order_item.json
48.  │   ├── product.json
49.  │   └── zip_geo.json
50.  ├── readme.md
51.  ├── run.sh
52.  └── teardown.sh

如上所示,我们的文档结构如上所示。我们的数据结构如下:

我们有如上的几个表格。它们之间的数据是相互关联的。我们知道在 Elasticsearch 中的数据,它不像传统的关系数据库,在查询的时候,我们可以通过 join 来丰富数据,而且为了能够提高数据的查询速度,我们最好把数据实现扁平化,这也就是的数据的非规范化(denormalization)。我们可以详细阅读文章 "Elasticsearch:Elasticsearch 中索引映射的非规范化"。在摄入数据的时候,我们希望把相关的内容最终能丰富到最后的文档中。我们希望实现如下的内容:

从上面的最终结果,我们可以看出来,我们需要的数据来自不同的表格。这个需要我们使用 enrich processor 来帮我们完成。

文件目录描述

在项目的目录(part-3)下面,我们可以看到如下的几个子目录:

  • data:在这个目录里它含有我们需要的各个数据以及它们的来源
  • mapping:在这个目录中,它含有各个表格数据的 mapping。通常我们并不需要预先定义数据的类型。我们可以让 Elasticsearch 帮我们自动识别数据的类型,但这往往不是最佳的。通过定义相应数据的 mapping,一方面它可以帮忙明确地定义数据字段的类型,比如 geo_point 数据类型,另一方面,通过设置 mapping,也可以提高数据的摄入速度
  • policy:在这个目录中,它定义了使用 enrich processor 时所需要的 policies。
  • pipeline:在这个目录里,它定义了在 enrich 时,我们需要使用到的 enrich processor
  • logstash:在这个目录里,它定义了 Logstash 需要使用到的配置文件

写入文档的顺序

由于我们的数据是一个关系数据表格,在我们写入数据的时候,我们先从上面图中的右边开始写入数据,这是因为左边的表格依赖于右边的表格。只有它们的数据是准备好的状态,那么我们才可以利用它们来丰富左边的表格。这也就是我们看到的如下的脚本:

如上图所示,我们可以看到

markdown 复制代码
1.  01-zip_geo.sh 
2.  02-customer.sh
3.  03-product.sh 
4.  04-order_item.sh
5.  05-order.sh 

这个其实就是我们执行脚本的顺序。我们需要按照上面的顺序从上到下来进行执行。

摄入数据

我们知道在我们摄入数据的时候,我们可以使用 Logstash 来写入 CSV 文档。Logstash 的好处是,它含有丰富的 filters 来供我们对数据进行处理。

针对 Elastic Stack 8.x 的安装来说,在默认的情况下,Elasticsearch 是带有安全的。针对自签名的集群来说,它通常还含有证书。针对带有安全的集群,我们可以参考文章 "Logstash:如何连接到带有 HTTPS 访问的集群"。下面,我们以摄入 zip_geo 为例来进行展示。在摄入数据的时候,我们需要使用到 fingerprint。我们可以参考文章 "Beats:使用 fingerprint 来连接 Beats/Logstash 和 Elasticsearch"。

在 logstash 目录下,我们可以看到如下的 zip_geo.conf 文档:

zip_geo.conf

ini 复制代码
1.  input {
2.    file {
3.      path => "##PROJECTPATH##/data/zip_geo/data.csv"
4.      start_position => "beginning"
5.      sincedb_path => "/dev/null" 
6.      mode => "read"
7.      exit_after_read => true
8.      file_completed_action => "log"
9.      file_completed_log_path => "##PROJECTPATH##/.logstash-status"
10.    }
11.  }

13.  filter {
14.    csv {
15.      autodetect_column_names => true
16.    }
17.    mutate {
18.      convert => {
19.        "zip" => "integer"
20.        "point" => "string"
21.      }
22.    }
23.  }

25.  output {
26.    elasticsearch {
27.      hosts => ["##ELASTICHOST##"]
28.      ssl => ##ELASTICSSL##
29.      user => "##ELASTICUSER##"
30.      password => "##ELASTICPASS##"
31.      index => "zip_geo"
32.      ssl => true
33.      ca_trusted_fingerprint => "##FINGERPRINT##"
34.    }
35.  }

这是一个标准的 Logstash 配置文件。在上面,我们可以看到一下奇奇怪怪的的像 ##PROJECTPATH## 这样的占位符号。这个需要在哪里配置呢?

我们回到项目的根目录下(part-3),我们可以看到一个叫做 env.sample 的文档。我们通过如下的命令来来创建一个叫做 .env 的文件:

bash 复制代码
cp env.sample .env

我们可以使用我们喜欢的编辑器来编辑这个 .env 文件:

bash 复制代码
vi .env
ini 复制代码
1.  PROJECTPATH="/home/parallels/data/elasticsearch-ingest/part-3"
2.  ELASTICHOST="192.168.0.3:9200"
3.  ELASTICSSL="true"
4.  ELASTICUSER="elastic"
5.  ELASTICPASS="h6y=vgnen2vkbm6D+z6-"
6.  FINGERPRINT="bd0a26dc646ef1cb3cb5e132e77d6113e1b46d56ee390dd3c6f0b2d2b16962c4"
7.  LOGSTASHPATH="/home/parallels/elastic/logstash-8.8.2"

我们根据自己的配置填入上面的信息。其中 FINGERPRINT 最为简单的办法就是通过 Kibana 的配置文件 config/kibana.yml 文件来获得。我们保存好上面的文件。这里其实就是定义的环境变量。我们接下来查看 1-zip_geo.sh 文件:

1-zip_geo.sh

bash 复制代码
1.  #!/bin/bash

3.  source ./.env

5.  hostprotocol="http"
6.  if [ "$ELASTICSSL" = "true" ]; then
7.    hostprotocol="https"
8.  fi

10.  curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/zip_geo"
11.  curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/zip_geo/_mapping" \
12.  -H "Content-Type: application/json" \
13.  -d @$PROJECTPATH/mapping/zip_geo.json

16.  logstashconf=`cat ${PROJECTPATH}/logstash/zip_geo.conf`
17.  logstashconf="${logstashconf//\#\#PROJECTPATH\#\#/"$PROJECTPATH"}"
18.  logstashconf="${logstashconf//\#\#ELASTICHOST\#\#/"$ELASTICHOST"}"
19.  logstashconf="${logstashconf//\#\#ELASTICSSL\#\#/"$ELASTICSSL"}"
20.  logstashconf="${logstashconf//\#\#ELASTICUSER\#\#/"$ELASTICUSER"}"
21.  logstashconf="${logstashconf//\#\#ELASTICPASS\#\#/"$ELASTICPASS"}"
22.  logstashconf="${logstashconf//\#\#FINGERPRINT\#\#/"$FINGERPRINT"}"
23.  $LOGSTASHPATH/bin/logstash -e "$logstashconf"

25.  curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/_enrich/policy/zip_geo_policy" \
26.  -H "Content-Type: application/json" \
27.  -d @$PROJECTPATH/policy/zip_geo.json

29.  sleep 30
30.  curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/_enrich/policy/zip_geo_policy/_execute"

上面的代码看起来很负责,一下子看不太明白。在开始的部分,我们从环境变量里得到 ELASTICSSL 的值。如果 Elasticsearch 集群的访问是 https 访问的,那么这个值应该设置为 true。这个在接下来的 curl 指令中需要用到。值得注意的是 :由于我们的集群是自签名的,我们使用 -k 选项来绕开证书的配置,尽管我们也可以通过设置来配置证书的访问。

记下来,我们使用 curl 指令来创建 zip_geo 索引。它的指令的格式有点类似:

bash 复制代码
curl -k -u elastic:h6y=vgnen2vkbm6D+z6- https://localhost:9200/zip_geo

如果是在 Kibana 中的 Dev Tools 中进行操作,它相当于:

PUT zip_geo

上述指令创建一个叫做 zip_geo 的指令。

接下来的指令,它相当于:

bash 复制代码
1.  curl -k -X PUT -u elastic:h6y=vgnen2vkbm6D+z6- "https://localhost:9200/zip_geo/_mapping" \
2.  -H "Content-Type: application/json" \
3.  -d /Users/liuxg/data/elasticsearch-ingest/part-3/mapping/zip_geo.json

上述命令相当于在 Kibana 中打入如下的命令:

bash 复制代码
1.  PUT zip_geo/_mapping
2.  {
3.    "properties": {
4.      "zip": {
5.        "type": "long"
6.      },
7.      "point": {
8.        "type": "geo_point"
9.      }
10.    }
11.  }

下面的代码:

ini 复制代码
1.  logstashconf=`cat ${PROJECTPATH}/logstash/zip_geo.conf`
2.  logstashconf="${logstashconf//\#\#PROJECTPATH\#\#/"$PROJECTPATH"}"
3.  logstashconf="${logstashconf//\#\#ELASTICHOST\#\#/"$ELASTICHOST"}"
4.  logstashconf="${logstashconf///\#\#ELASTICSSL\#\#/"$ELASTICSSL"}"
5.  logstashconf="${logstashconf//\#\#ELASTICUSER\#\#/"$ELASTICUSER"}"
6.  logstashconf="${logstashconf//\#\#ELASTICPASS\#\#/"$ELASTICPASS"}"
7.  logstashconf="${logstashconf//\#\#FINGERPRINT\#\#/"$FINGERPRINT"}"
8.  ./bin/logstash -e "$logstashconf"

这部分代码的真正意思是替换 zip_geo,conf 里含有 "## ... ##" 部分的字符串进行替换。如果你对这个不是很熟悉的话,请参阅网上的链接。在上面的最后部分,我们使用 Logstash 来运行在 logstashconf 变量里的管道。

下面的代码:

bash 复制代码
1.  curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/_enrich/policy/zip_geo_policy" \
2.  -H "Content-Type: application/json" \
3.  -d @$PROJECTPATH/policy/zip_geo.json

它用来运行 zip_geo_policy 以生成相应的 .enrich_zip_geo_policy,,,,, 索引。它想到于如下的命令:

bash 复制代码
1.  curl -k -X PUT -u elastic:h6y=vgnen2vkbm6D+z6- "https://localhost:9200/_enrich/policy/zip_geo_policy" \
2.  -H "Content-Type: application/json" \
3.  -d @$PROJECTPATH/policy/zip_geo.json

在 Kibana 中,我们可以打入如下的命令来实现同样的功能:

bash 复制代码
1.  PUT /_enrich/policy/zip_geo_policy
2.  {
3.    "match": {
4.      "indices": "zip_geo",
5.      "match_field": "zip",
6.      "enrich_fields": ["point"]
7.    }
8.  }

由于生成丰富索引需要一定的时间,在脚本的部分,我们挂起 30 秒的时间,当然这个依赖于数据量的多少。

在最后的部分,我们执行:

bash 复制代码
curl -k -X PUT -u $ELASTICUSER:$ELASTICPASS "$hostprotocol://$ELASTICHOST/_enrich/policy/zip_geo_policy/_execute"

它相当于执行:

ini 复制代码
curl -k -X PUT -u elastic:h6y=vgnen2vkbm6D+z6- "https://localhost:9200/_enrich/policy/zip_geo_policy/_execute"

在 Kibana 中,我们可以通过如下的命令来完成相应的功能:

bash 复制代码
 2.  PUT /_enrich/policy/zip_geo_policy/_execute

好了,让我们来执行第一个脚本:

运行完,我们的第一个脚本后,我们可以在 Kibana 中进行查看:

我们按照同样的套路依次执行如下的脚本:

markdown 复制代码
1.  02-customer.sh
2.  03-product.sh 
3.  04-order_item.sh
4.  05-order.sh 

在运行完 02-customer.sh 后,我们可以看到:

我们接着运行 02-product.sh 脚本。我们可以查看到 product 索引的文档:

我们再接着运行 04-order_item.sh 脚本:

我们接下来运行 05-order.sh:

从上面,我们可以看到我们最终想要的结果。

为了能删除所有之前创建的资源,我们可以一键删除:

bash 复制代码
./teardown.sh

然后,我们可以再使用一个命令来完成所有的运行:

ruby 复制代码
1.  parallels@ubuntu2004:~/data/elasticsearch-ingest/part-3$ cat run.sh
2.  ./01-zip_geo.sh
3.  ./02-customer.sh
4.  ./03-product.sh
5.  ./04-order_item.sh
6.  ./05-order.sh
arduino 复制代码
./run.sh

特别注意的一点是,我们的 enrich processor 是在 ingest pipeline 里被调用的,比如:

ini 复制代码
1.  output {
2.    elasticsearch {
3.      hosts => ["##ELASTICHOST##"]
4.      ssl => ##ELASTICSSL##
5.      user => "##ELASTICUSER##"
6.      password => "##ELASTICPASS##"
7.      index => "customer"
8.      pipeline => "customer_pipeline"
9.      ca_trusted_fingerprint => "##FINGERPRINT##"    
10.    }
11.  }

你可以在地址下载所有的代码:GitHub - evermight/elasticsearch-ingest

相关推荐
hengzhepa4 小时前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
bubble小拾12 小时前
ElasticSearch高级功能详解与读写性能调优
大数据·elasticsearch·搜索引擎
不能放弃治疗13 小时前
重生之我们在ES顶端相遇第 18 章 - Script 使用(进阶)
elasticsearch
hengzhepa13 小时前
ElasticSearch备考 -- Search across cluster
学习·elasticsearch·搜索引擎·全文检索·es
Elastic 中国社区官方博客15 小时前
Elasticsearch:使用 LLM 实现传统搜索自动化
大数据·人工智能·elasticsearch·搜索引擎·ai·自动化·全文检索
慕雪华年16 小时前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch
Elastic 中国社区官方博客18 小时前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
alfiy19 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
alfiy20 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
丶21362 天前
【大数据】Elasticsearch 实战应用总结
大数据·elasticsearch·搜索引擎