Logstash 从 Elasticsearch 抽取索引文档信息到 Kafka 的实践分享
一、背景与需求
在数据处理和分析的场景中,经常需要将 Elasticsearch 中的索引文档信息抽取出来,并传输到 Kafka 中进行后续处理。本文将分享如何使用 Logstash 8.18.1 工具实现从 Elasticsearch 8.1.1 抽取索引文档信息,并将其发送到 Kafka 2.13-2.8.2 的完整流程。
二、环境与工具
• Logstash:8.18.1
• Elasticsearch:8.1.1
• Kafka:2.13-2.8.2
• jq:用于处理 JSON 数据
• Shell 脚本:用于执行 Elasticsearch 查询并处理结果
三、配置与实现
(一)Logstash 配置文件(logstash.conf
)
以下是 Logstash 的配置文件内容,它分为input
、filter
和output
三个部分。
1.Input
通过exec
插件调用 Shell 脚本es_query.sh
,从 Elasticsearch 查询数据。
input {
exec {
command => "/data/logstash-8.18.1/scripts/es_query.sh"
interval => 120
codec => "json"
tags => ["es_data"]
}
}
2.Filter
对查询结果进行处理,包括拆分数组、提取字段、移除不需要的字段等。
filter {
if "es_data" in [tags] {
if [hits][hits] {
split {
field => "[hits][hits]"
}
} else {
mutate {
add_tag => "query_failure"
}
ruby {
code => 'event.set("query_error", event.get("error"))'
}
}
ruby {
code => '
if event.get("hits") && event.get("hits").is_a?(Hash) && event.get("hits")["hits"].is_a?(Array)
event.get("hits")["hits"].each do |hit|
src = hit["_source"]
if src && src.is_a?(Hash)
event.set("appName", src["appName"]) if src.key?("appName")
end
end
end
'
}
mutate {
remove_field => ["took", "timed_out", "_shards", "max_score", "error", "process", "@version", "event", "host", "tags", "@timestamp"]
}
mutate {
remove_field => ["_score", "_type", "_index", "_version", "_shards", "_seq_no", "_primary_term"]
remove_field => ["@timestamp", "@version", "message"]
}
mutate {
rename => { "[hits][hits][_source]" => "doc" }
remove_field => ["hits"]
}
mutate {
add_field => {
"xxx" => "%{[doc][xxx]}"
"yyy" => "%{[doc][yyy]}"
"zzz" => "%{[doc][zzz]}"
}
remove_field => ["doc"]
}
}
}
3.Output
将处理后的数据发送到 Kafka,或者在查询失败时输出到控制台。
output {
if "query_failure" in [tags] {
stdout { codec => rubydebug }
} else {
kafka {
bootstrap_servers => "2.2.2.2:9092"
topic_id => "es_log_topic"
security_protocol => "SASL_PLAINTEXT"
sasl_mechanism => "PLAIN"
sasl_jaas_config => 'org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="123456";'
codec => json
}
}
}
(二)Elasticsearch 查询脚本(es_query.sh
)
该脚本负责从 Elasticsearch 查询数据,并将结果返回给 Logstash。
#!/bin/bash
LAST_TIME_FILE="/data/logstash-8.18.1/status/last_run_time.txt"
# 读取上次时间戳(确保为数值类型)
LAST_TIME=$(cat "$LAST_TIME_FILE" 2>/dev/null || echo "1747238400000")
LAST_TIME=$(echo "$LAST_TIME" | head -n 1 | tr -d '\n' || echo "1747238400000")
# 使用 HEREDOC 语法创建 JSON,避免变量替换问题
QUERY_JSON=$(cat <<EOF
{
"query": {
"bool": {
"must": [
{ "term": { "xxx": "12345678" }},
{
"range": {
"logTime": {
"gt": $LAST_TIME,
"format": "epoch_millis"
}
}
}
]
}
},
"sort": [
{
"logTime": "asc"
},
{