LogStash 原理和使用(十六)

这篇我们分析LogStash 原理和使用:
 
LogStash 是一个类似实时流水线的开源数据传输引擎,它像一个两头连接不 同数据源的数据传输管道,将数据实时地从一个数据源传输到另一个数据源中。 在数据传输的过程中,LogStash 还可以对数据进行清洗、加工和整理,使数据在 到达目的地时直接可用或接近可用,为更复杂的数据分析、处理以及可视化做准 备。既然需要将数据搬运到指定的地点,为什么不在数据产生时就将数据写到需 要的地方呢?
这个问题可以从以下几个方面理解。
首先,许多数据在产生时并不 支持直接写入到除本地文件以外的其他数据源。比如大多数第三方软件在运行中 产生的日志,都以文本形式写到本地文件中。
其次,在分布式环境下许多数据都 分散在不同容器甚至不同机器上,而在处理这些数据时往往需要将数据收集到一 起统一处理。
最后,即使软件支持将数据写入到指定的地点,但随着人们对数 据理解的深人和新技术的诞生又会有新的数据分析需求出现,总会有一些接入需 来是原生软件 无法满足的。综上,LogStash 的核心价值就在于它将业务系统与数摆处现系统隔离开来,屏蔽了各自系统变化对彼此的影响,使系统之间的依赖 降低并可独自进化发展。 LogStash 可以从多个数据源提取数据,然后再清洗过滤并发送到指定的目标 数据源。目标数据源也可以是多个,而且只要修改 LogStash 管道配置就可以轻松 扩展数据的源头和目标。这在实际应用中非常有价值,尤其是在提取或发送的数 据源发生变更时更为明显。比如原来只将数据提取到 Elasticsearch 中做检索,但 现在需要将它们同时传给 Spark 做实时分析。如果事先没有使用 LogStash 就必须 设计新代码向 Spark 发送数据,而如果预先使用了 LogStash 则只需要在管道配置 中添加新的输出配置。这极大增强了数据传输的灵活性。
安装 Logstash
Logstash 是基于 Java 生态圈的语言开发的,所以安装 Logstash 之前需要先 安装 JDK Logstash 7 目前只支持 Java8 Java 11 ,所以安装前要检查安装 JDK 的版本是否正确。Logstash 提供了 DEBh RPM 安装包,还提供了 tar. gz zip 压缩包,也可以直接通过 Docker 启动 Logstash 。安装过程比较简单,直接解压 缩文件是最简单的办法。
 

 

启动 Logstash
Logstash 的启动命令位于安装路径的 bin 目录中,直接运行 logstash 不行, 需要按如下方式提供参数:
./logstash -e "input {stdin {}} output {stdout{}}" 启动时应注意: -e 参数后要使用双引号。如果在命令行启动日志中看“Successfully started Logstash API end-point l:port= >9600 ”,就证明启动成功。

在上面的命令行中,-e 代表输入配置字符串,定义了一个标准输入插件 ( stdin) 和一个标准输出插件( stdout), 意思就是从命令行提取输入,并在命令行直接 将提取的数据输出。如果想要更换输入或输出,只要将 input output 中的插 件名称更改即可,这充分体现了 Logstash 管道配置的灵活性。按示例启Logstash,命令行将会等待输入,键人“ Hello, World!" 后会在命令行返回结果如 下
在默认情况下, stdout 输出插件的编解码器为 rubydebug, 所以输出内容中 包含了版本、时间等信息,其中 message 属性包含的就是在命令行输入的内容。 试着将输出插件的编码器更换为 plain line ,则输入的结果将会发生变化 :
./logstash -e "input {stdin {}} output {stdout{codec => plain}}"

连接 Elasticsearch
Logstash 基于插件开发和应用,包括输入、过滤器和输出三大类插件。输 入插件指定了数据来源,过滤器插件则对数据做过滤清洗,而输出插件则指定了 数据将被传输到哪里。在示例 1-5 中启动 Logstash 时,是通过命令行并使用 -e 参数传入了配置字符串,指定了标准输入 stdin 插件和标准输出 stdout 插件。但 在实际应用中,通常都是使用配置文件指定插件。 配置文件的语法形式与命令行相同,要使用的插件是通过插件名称来指定。 例如,想要向 Elasticsearch 中发送数据,则应该使用名称为 elasticsearch 的输 出插件。在Logstash 安装路径下的 config 目录中,有一个名为 logstash-sample. conf 的文件,提供了配置插件的参考。 这个文件配置的输入插件为 beats, 输出插件为 elasticsearch 。复制这个文件 并重命名为 std_es. conf ( 也可以直接创建空文件 ) ,下面通过修改这个文件配置 一个从命令行提取输入,并传输到 Elasticsearch Logstash 实例。按如下内 容修改 std_es. conf 文件的输入输出插件 :
input {
stdin {
    }
}
output {
elasticsearch {
hosts => ["http://172.18.194.140:9200"]
index => "mystdin"
#user => "elastic"
#password => "changeme"
    }
}
在上面的配置中, easticsearch 输出插件中的 hosts 参数指定了 Elasticsearch 地址和端口,index 参数则指定了存储的索引。 Elasticsearch 索 引不需要预先创建,但要保证它启动的地址和端口与配置文件中的一致。按如下 方式启动 Logstash:
logstash -f ../config/std_es.conf 其中,-f 参数后面指定了配置文件的路径。启动后如果没有异常,可在命令 行窗口中输入"Hello, World!" 等任意字符串, Logstash 将把输入内容提取到指 定的 Elastiesearch 服务中。通过 Kibana 开发工具输入 GET _cat/indices, 可以 看到 mystdin 这个索引已经创建出来了。

 输入 GET /mystdin/_search, 则返回结果为

通过上图可以看到, Elasticsearch 为输入创建了一个 mystdin 索引,在命 令行输入的"Hello, World!" 已经被索引,在返回结果的 _ source 字段上可以看 到文档内容。
Logstash 体系结构
Logstash 数据传输管道所具备的流水线特征,体现在数据传输过程分为三 个阶段-- 输入、过滤和输出。这三个阶段按顺序依次相连,像一个加工数据的流 水线。 在实现上,它们分别由三种类型的插件实现,即输入插件、过滤器插件 和输出插件,并可通过修改配置文件实现快速插拔。除了这三种类型的插件以外, 还有种称为编解码器 (Codec) 的插件。编解码器插件用于在数据进人和离开管 道时对数据做解码和编码,所以它一般都是与具体的输入插件或输出插件结合起 来使用。事件 (Event) Logstash 中另一个比较重要的概念, 它是对 Logstash 处 理数据的一种面向对象的抽象。如果将 Logstash 比喻为管道,那么事件就是流
淌在管道中的水流。事件由输入插件在读入数据时产生,不同输入插件产生事件 的属性并不完全相同,但其中一定会包含有读入的原始数据。过滤器插件会对这 些事件做进步处理, 处理的方式主要体现在对事件属性的访问、添加和修改。 最后,输出插件会将事件转换为目标数据源的数据格式并将它们存储到目标数据 源中。在 Logstash 管道中,每个输入插件都是在独立的线程中读取数据并产生事 件。但输入插件并不会将事件直接传递给过滤器插件或输出插件,而是将事件写 人到一个队列中。队列可以是基于内存的,也可以是基于硬盘的可持久化队列。 Logstash 管道会预先生成一组工作线程,这些线程会从队列中取出事件并在过 滤器中处理,然后再通过输出插件将事件输出。事件队列可以协调输入插件与过 滤器插件、输出插件的处理能力,使得 Logstash 具备了一定的消峰填谷能力。 除了输入插件使用事件队列与过滤器插件、输出插件交互以外,Logstash 还 在输出插
与目标数据源之间提供了一个死信队列(Dead Letter Queue) 。死信 队列会在目标数据源没有成功接收到数据时,将失败的事件写人到队列中以供后 续做进步处理。 输入插件、过滤器插件、输出插件、编解码器插件以及事件、队列等组件, 共同协作形成了整个 Logstash 的管道功能,它们构成 Logstash 的体系结构,
如图所示。
 
 
插件
插件 (Plugin) 通过简单的配置就可接入系统并增强系统功能。 Logstash 提供 了丰富的输入、过滤器、输出和编解码器插件,它们也都是通过配置接入系统并 增强 Logstash 在某一方面的功能。 输入插件的作用是使数据进入管道并生成数据传输事件,过滤器插件则对进 人管道的事件进行修改、清洗等预处理,而输出插件则将过滤器处理好的事件发 送到目标数据源。输入插件和输出插件都可以使用编解码器在数据进入或退出管 道时对数据进行编码或解码,使数据以用户期望的格式进入或退出管道。插件开发都很便捷,一般都会提供统一接口作为开发框架,开发人员只要遵 从接口规范并编写逻辑就可以开发出新的插件。Logstash 插件使用 Ruby 语言 开发,感兴趣或者有需求的同学可以自行了解下。
logstash-plugin 命令
Logstash 官方提供的插件并非全部绑定在 Logstash 中,有一部分插件需要 用户在使用时手工安装,比如 log4j 输入插件在默认情况下就没有安装。 Logstash 提供了一条插件管理的命令 logstash-plugin, 可以用于查看、安装、更新或删除 插件。除了 Logstash 官方提供的插件以外,用户还可以根据需要自定义插件, 这些插件也需要使用 logstash- plugin 命令管理。有关 logtash- plugin 的具体使 用方法,可通过执行 lgstash-plugin -help 查看帮助。

插件配置
Logstash 插件的可插拔性,除了体现在可通过 logstash-plugin 命令方便地 安装与删除以外,还体现在已安装插件的使用和关闭仅需要通过简单的配置即可 实现。Logstash 配置文件分为两类,一类是用于设置 Logstash 自身的配置文件, 主要是设置 Logstash 启动、执行等基本信息的配置文件。这类配置文件位于 Logstash 安装路径的 config 目录中,包括 logstash. yml pipelines. yml jvm. options、 log4j. properties 等文件。在这些配置文件中, logstash. yml 文件是核 心配置文件,采用的语法格式为 YAML; 其余文件分别用于配置 JVM log4j
 
另一类配置就是设置 Logstash 管道的配置文件了,它们用于设置 Logstash 如何应用这几种插件组成管道,是应用 Logstash 最核心的内容之一。 最简单的配置 Logstash 管道的方式就是我们前面展示的方式,通过 logstash 命令参数 -e 配置管道。再有一种方式就是通过 -f 参数指定管道配置文件 的路径,以配置文件的形式设置 Logstash 管道。 Logstash 在启动时会自动扫 描目录,并加载所有以. conf 为扩展名的配置文件,所以用户可以将 Logstash 的管道配置文件放置在这个目录中。 Logstash 管道配置的语法格式不是 YAML, 它的语法格式是更接近 Ruby 哈 希类型的初始化格式。
事件
Logstash 事件由一组属性组成,包括数据本身、事件产生时间、版本等。 不同输入插件产生事件的属性各不相同,这些事件属性可以在过滤器插件和输出 插件中访问、添加、修改或是删除。 由于事件本身由输入插件产生,所以在输入插件中不能访问事件及其属性。 这里所说的对事件及其属性的访问是指在 Logstash 管道配置中的访问,比如过 滤器插件配置中根据事件属性执行不同的过滤等。 在事件属性中有一个比较特殊的属性 tags,它的类型为数组,包含了插件在 处理事件过程中为事件打上所有标签。比如插件在处理事件中发生了异常,一般 都会为事件添加一个异常标签。标签本身就是一个字符串,没有特别的限制。事
件的标签在一开始的时候都是空的,只有插件为事件打上了新标签,这个属性才 会出现在输出中。所以,总体来说可以认为事件是一组属性和标签的集合。
访问事件属性
在管道配置中访问事件属性的最基本语法形式是使用方括号和属性名,例如 [ name ]代表访问事件的 name 属性 ; 如果要访问的属性为嵌套属性,则需要使用 多层次的路径,如[ parent][ child] 相当于访问 parent. child 属性 ; 如果要访问的属 性为事件的最顶层属性则可以省略方括号。 事件中有哪些属性取决于输入插件的类型,但有一些事件属性几乎在所有事 件中都有,比如@version @ timestamp @ metadata 等。这类属性大多以 @开头,可以认为是事件的元属性。其中, @version 代表了事件的版本,
@timestamp 是事件的时间戳。 @metadata 与前述两个属性不同,它在默认情况下是一个空的散列表 ( Hash table)。 @ metadata 最重要的特征一般不会在最终的输出中出现,即使 在插件中向这个散列表中添加了内容也是如此。(只有当输出插件使用 rubydebug 解码器,并且将它的 metadata 参数设置为 true, @ metadata 属性才 会在输出中显示):
code => "event. set ('[ @ metadata][hello]' 'world' ) " @ metadata 属性设计的目的并不是为了给输出添加数据,而是为了方便插 件做数据运算。它类似于一个共享的存储空间,在过滤器插件和输出插件中都可 以访问。因为在实际业务有一些运算结果是需要在插件间共享而又不需要在最终 结果中输出,这时就可以将前一插件处理的中间结果存储在@ metadata 中。 除了使用方括号访问事件属性以外,在插件参数中还可以通过 “%{ field_name}" 的形式访向事件属性,其中 field. name 就是前述的方括号加
属性名的形式。例如,在文件输出插件中将日志根据级别写人到不同的文件中 :
output {
file{
path => "/var/log/%{loglevel}. log"
    }
}
在上面的例子中,
loglevel 是当前事件的一个属性名称,file 输出插件的 path 参数通过%{ loglevel} 的形式读取这个属性的值,并以它的值为日志文件名称。
事件 API
事件 API 主要是在一些支持 Ruby 脚本的插件中使用等。这些插件一般都有 一个 code 参数接收并运行 Ruby 脚本,在这些脚本中就可以使用 event 内置对 象访问、修改或者删除事件属性。
队列
在互联网时代,许多活动或突发事件会导致应用访问量在某一时间点瞬间呈 几何式增长。在这种情况下,应用产生的数据也会在瞬间爆发,而类似 Logstash 这样的数据管道要搬运的数据也会突然增加。如果没有应对这种瞬间数据爆炸的 机制,轻则导致应用数据丢失,重则直接导致系统崩溃,甚至引发雪崩效应将其 他应用一并带垮。 应对瞬间流量爆炸的通用机制是使用队列,将瞬间流量先缓存起来再交由后 台系统处理。后台系统能处理多少就从队列中取出多少,从而避免了因流量爆炸 导致的系统崩溃。 Logstash 输入插件对接的事件队列实际上就是应对瞬间流量爆炸、提高系 统可用性的机制,它利用队列先进先出的机制平滑事件流量的峰谷,起到了削峰 填谷的重要作用。除了输入插件使用的事件队列,输出插件还有一个死信队列。 这个队列将会保存输出插件没有成功发送出去的事件,它的作用不是削峰填谷而 是容错。
持久化队列
Logstash 输入插件默认使用基于内存的事件队列,这就意味中如果 Logstash 因为意外崩溃,队列中未处理的事件将全部丢失。不仅如此,基于内 存的队列容量小且不可以通过配置扩大容量,所以它能起到的缓冲作用也就非常 有限。为了应对内存队列的这些问题,可以将事件队列配置为基于硬盘存储的持 久化队列( Persistent Queue) 。 持久化队列将输入插件发送过来的事件存储在硬盘中,只有过滤器插件或输 出插件确认已经处理了事件,持久化队列才会将事件从队列中删除。当 Logstash 因意外崩溃后重启,它会从持久化队列中将未处理的事件取出处理,所以使用了 持久化队列的 Logstash 可以保证事件至少被处理一次。
如果想要开启 Logstash 持久化队列,只要在 logstash. yml 文件中将 queue. type 参数设置为 persisted 即可,它的默认值是 memory 。当开启了持久化队列 后,队列数据默认存储在 Logstash 数据文件路径的 queue 目录中。数据文件路
径默认是在 Logstash 安装路径的 data 目录,这个路径可以通过 path. data 参 数修改。持久化队列的存储路径则可以通过参数 path. queue 修改,它的默认值 是${ path. data |/ queue 。 尽管持久化队列将事件存储在硬盘上,但由于硬盘空间也不是无限的,所以 需要根据应用实际需求配置持久化队列的容量大小。Logstash 持久化队列容量 可通过事件数量和存储空间大小两种方式来控制,在默认情况下 Logtash 持久 化队列容量为 1024MB 1CB, 而事件数量则没有设置上限。当持久化队列达到
了容量上限, Logstash 会通过控制输入插件产生事件的频率来防止队列溢出, 或者拒绝再接收输入事件直到队列有空闲空间。持久化队列事件数量容量可通过 queue. max events 修改,而存储空间容量则可通过 queue. max bytes 来修改。
事实上在许多高访问量的应用中,单纯使用 Logstash 内部队列的机制还是 远远不够的。许多应用会在 Logstash 接收数据前部署专业的消息队列,以避免 瞬间流量对后台系统造成冲击。这就是人们常说的 MQ ( Message Queue) ,比 如 Kafka RocketMQ 等。这些专业的消息队列具有千万级别的数据缓存能力, 从而可以保护后续应用避免被流量压跨。所以在 Logstash 的输入插件中也提供 了一些对接 MQ 的输入插件,比如 kafka rabbitmq 等。
死信队列
Logstash 输入插件的事件队列位于输入插件与其他插件之间,而死信队列 则位于输出插件与目标数据源之间。如果 Logstash 处理某一事件失败,事件将 被写入到死信队列中。 Logstash 死信队列以文件的形式存储在硬盘中,为失败事件提供了采取补
救措施的可能。死信队列并不是 Logstash 中特有的概念,在许多分布式组件中 都采用了死信队列的设计思想。由于死信队列的英文名称为 Dead Letter Queue, 所以在很多文献中经常将它简写为 DLQ 。 Logstash 在目标数据源返回 400 404 响应状态码时认为事件失败,而支 持这种逻辑的目标数据源只有 Elasticsearch 。 所以 Logstash 死信队列目前只 支持目标数据源为 Elasticsearch 的输出插件,并且在默认情况下死信队列是关 闭的。开启死信队列的方式与持久化队列类似,也是在 logstash. yml 文件中配 置,参数名为 dead_ letter_queue.enable 。死信队列默认存储在 Logstash 数据 路径下的 dead_letter_queue 目录中,可通过 path. dead_ letter. _queue 参数 修改。死信队列同样也有容量上限,默认值为 1024MB, 可通过
dead_letter_queue.max_bytes 参数修改。 虽然死信队列可以缓存一定数量的错误事件, 但当容量超过上限时它们还 是会被删除,所以依然需要通过某种机制处理这些事件。Logstash 为此专门提 供了一种死信队列输入插件,它可以将死信队列中的事件读取出来并传输至另一 个管道中处理。
管道配置
Logstash 安装路径下的 bin 目录包含了一些重要的命令,启动 Logstash 管 道就是通过其中的 logstash 命令实现。
logstash 命令在执行时会读取管道配置, 然后根据管道配置初始化管道。管道配置可通过命令行-e 参数以字符串的形式
提供,也可以通过命令行 -f 参数以文件形式提供。前者定义管道配置的方式称为 配置字符串(Config String) 后者则是配置文件,这两种方式只能任选其一而不能 同时使用。 在 logstash. yml 配置文件中,也包含了 config. string path. config 两个
参数,分别用于以上述两种方式配置默认管道。 logstash 命令与 logstash. yml 配置文件之间还有许多这样用于配置管道的
共享参数,下面就先来看看这些配置参数。
主管道配置
Logstash 启动后会优先加载在 logstash. yml 文件中配置的管道,并且为这 个管道指定惟一标识 main, 我们可以称这个管道为主管道。无论是通过 -e 参数以 配置字符串的形式创建管道, 还是通过-f 参数以配置文件的形式创建管道,它们在默认情况下都是在修 改主管道的配置。既然有主管道存在,那么是不是还可以配置其他管道呢? 答案 是肯定的。事实上 Logstash 可以在一个进程中配置多个管道,不同的是主管道是在 logstash. yml 文件中配置,而其他管道则是在 pipeline. yml 文件中配置。 但是 pipelie. yml 中配置的管道与主管道互斥,如果在 logstash. yml 文件中或是 使用 logstash 命令行的 -e -f 等参数配置了主管道,那么 pipeline. yml 文件中 配置的其他管道就会被忽略。只有主管道缺失,logstash 命令才会尝试通过 pipeline. yml 文件初始化其他管道。无论是主管道还是其他管道,它们的配置参 数都是相同的。在 logstash. yml 文件中主管道配置参数范例如下 :
pipeline.id: main
pipeline.workers: 2
pipeline.batch.size: 125
pipeline.batch.delay: 50
pipeline.unsafe_shutdown: false
其中:
pipeline. id 用于设置管道的 ID
pipelne. workers 则用于设置并发处理事件的线程数量,默认情况下与所
在主机 CPU 核数相同
pipeline.batch.size: 每个工作线程每批处理事件的数量
pipeline.batch.delay: 工作线程处理事件不足时的超时时间
pipeline.unsafe_shutdown: 如果还有未处理完的事件,是否立即退出 Logstash 处理事件并不是来一个处理一 个, 而是先缓存 125 个事件或超过 50ms 后再统一处理。 由于使用了缓存机制,所以当 Logstash 管道因意外崩 溃时会丢失已缓存事件。pipeline. unsafe_ shutdown 参数用于设置在 Logstash 正常退出时,如果还有未处理事件是否强制退出。在默认情况下,Logstash 会 将未处理完的事件全部处理完再退出。如果将这个参数设置为 true, 会因为强制 退出而导致事件丢失。同时,这个参数也解决不了因意外崩溃而导致缓存事件丢 失的问题。
单管道配置
一个 Logstsh 实例可以运行一个管道也可以运行多个管道,它们相互之间可 以不受任何影响。一般来说,如果只需要运行一个管道可以使用 logstash. yml 配置的主管道;而在需要运行多个管道时才会使用 pipeline. yml 配置。无论是单 管道还是多管道,对于其中某一具体管道的配置格式完全一致。这种格式不仅在 配置文件中有效,在使用字符串配置管道时也是有效的。
语法格式
管道配置由 3 个配置项组成,分别用于配置输入插件、过滤器插件和输出插 件,如下面的示例所示。尽管输入插件、过滤器插件和输出插件在处理数据时按 顺序进行,但在配置文件中它们的顺序并不重要,而且它们也都不是必要配置。 所有插件配置都必须要在这三个配置项中,插件是哪种类型就应该放置在哪个配置项中。每一个配置项可以放多个插件配置,并可以通过一些参数设置这些 插件的特性。
input {
……
}
filter {
……
}
output {
…..
}
一个插件的具体配置由插件名称和一个紧跟其后的大括号组成,大括号中包 含了这个插件的具体配置信息。虽然编解码器也是一种插件类型, 但由于只能 与输入或输出插件结合使用,所以编解码器只能在输入或输出插件的 codec 参 数中出现。例如,在示例 12-7 中就配置了一个 stdin 输入插件、一个 aggregate 过滤器插件和一个 stdout 输出插件。其中, stdin 使用的编解码器 mutiline 也是 一个插件, 它的配置也遵从插件配置格式,由编解码器插件名称和大括号组成。 在编解码器 muliline 的大括号中配置了 patterm what 两个参数,而在过滤器 插件 aggregate 的大括号中则配置了 task. _id code 两个参数。
input { stdin{
codec => multiline {
pattern => "^\s"
what => "previous"
       }
   }
}
filter {
aggregate {
task id => "%{message}"
code => "event.set ('val', event.get('val')==nil?11:22)"
     }
}
output {stdout { }}
插件参数的格式与插件本身的配置在格式上有些相同,但又有着比较明显的 区别。插件配置在插件名称与大括号之间是空格,而插件参数则是使用“=> ” 关联起来的键值对。其中,键是插件参数名称,而值就是参数值。这种格式与 Ruby 哈希类型的初始化一样,所以本质上来说每个插件的配置都是对 Ruby 哈 希类型的初始化。 管道配置的这种格式中还可以添加注释,注释以 “# ”开头,可以位于文件 的任意位置。在 Logstash 安装路径的 config 目录中,有一个 logstash- sample. conf 的样例配置文件,可以在配置管道时参考。
多管道配置
Logtash 应用多管道通常是由于数据传输或处理的流程不同,使得不同输入 事件不能共享同一管道。假如 Logstash 进程运行的宿主机处理能力超出一个管 道的需求,如果想充分利用宿主机的处理能力也可以配置多管道。当然在这种情 况下,也可以通过在宿主机上启动多个 Logstash 实例的方式,充分挖掘宿主机 的处理能力。但多进程单管道的 Logstash 比单进程多管道的 Logstash 占用资 源会更多,单进程多管道的 Logstash 在这种情况下就显现出它的意义了。 多管道虽然共享同- Logstash 进程,但它们的事件队列和死信队列是分离的。 在使用多管道的情况下,要分析清楚每个管道的实际负载,并以此为依据为每个
管道分配合理的计算资源,起码每个管道的工作线程数量 pipeline.workers 应该 与工作负载成正比。 配置单进程多管道的 Logstash,是通过 pipeline. yml 配置文件实现的。 在启动Logstash 时,如果没有设置主管道信息, Logstash 读取 pipeline. yml
文件以加载管道配置信息。 pipeline. yml 通过 config. string path. config 参数 以配置字符串或配置文件的形式为每个管道设置独立的配置信息,还可以设置包 括事件队列、管道工作线程等多种配置信息。pipeline. yml 文件也采用 YAML 语法格式,它使用 YAML 中的列表语法来 定义多个管道,在每个列表项中通过键值对的形式来定义管道的具体配置。默认 情况下,logstash. yml 没有配置主管道,而 pipeline. yml 文件的内容也全部注 释了,所以直接无参运行 logstash 时会报 pipeline. yml 文件为空的错误。配置 范例如下:
- pipeline.id: test
pipeline.workers: 1
pipeline.batch.size: 1
config.string: "input { generator {} } filter { sleep { time => 1 } } output
{stdout { .. } }"
- pipeline.id: another_test
queue.type: persisted
path.config: "/tmp/logstash/*.config"
配置了两组管道,它们的惟一标识分别是 test another_test test 管道 使用 confg sting 直接设置了管道的插件信息,而 another_ test 则通过 path. config 指定了管道配置文件的路径。可见, pipeline. yml 配置多管道时使用的参 数与 logstash. yml 中完全一致,它还可以使用配置队列和死信队列的参数,只 是这些参数都只对当前管道有效。
编解码器插件
Logstash 管道中传递是事件,所以输入和输出插件都存在数据与事件的 编码或解码工作。为了能够复用编码和解码功能,Logstash 将它们提取出来抽 象到一个统一的组件中, 这就是 Logstash 的编解码器插件。由于编解码器在输 入和输出时处理数据,所以编解码器可以在任意输入插件或输出插件中通过 codec 参数指定。
plain 插件
Logstash 版本 7 中一共提供了 20 多种官方编解码器插件,在这些编解码器 插件中最为常用的是 plain 插件,有超过八成的输入和输出插件默认使用的编解 码器插件就是 plain 。 plain 编解码器用于处理纯文本数据,在编码或解码过程中没有定义明确的
分隔符用于区分事件。与之相较, line 编解码器则明确定义了以换行符作为区分 事件的分隔符,每读入行文本就会生成一个独立的事件,而每输出一个事件也会 在输出文本的结尾添加换行符。line 编解码器符合人们处理文本内容的习惯,所 以也是种比较常用的编解码器。 除了 plain line 编解码器以外, json 编解码 器是另一种较为常用的编解码器,主要用于处理 JSON 格式的文本数据。 尽管 plain 编解码器非常重要,但它在使用上却非常简单,只有 charset 和 format 两个参数。其中, charset 用于设置文本内容采用的字符集,默认值为 UTF-8;而 format 则用于定义输出格式,只能用于输出插件中。 format 参数定义 输出格式时,采用的是 “%{} ”形式,例如 :
input { stdin {codec => line }
}
output{
stdout{
codec => plain {
format => "The message is % {[message]}\nIt's
from %{[host]}\n"
         }
     }
}
在示例中, Logstash 在标准输入 ( 即命令行 ) 等待输入,并将输入内容按 format 参数定义的格式以两行打印在标准输出中。
line 编解码器
以行为单位对文本数据进行解码时,每 - 行都有可能成为一个独立事件 ; 而在 编码时,每个事件输出结尾都会添加换行符。以行为单位的编解码器有 line 和 muliline 两种,前者以单行为输入事件,而后者则根据一定条件将多行组装成一 个事件。
multiline 编解码器也是以行为编解码的单元,但在它编解码的事件中可能会 包含一行也有可能会包含多行文本。multiline 编解码器对于处理日志中出现异 常信息时非常有用,它能将异常合并到同一个日志事件中。例如,在下面中所示 的一段日志文本, 从是一个 Java 异常打印出来的堆栈信息,在逻辑上它们都 应该归属于 ERROR 日志 :
 
一般来说,正常日志都以方括号“ [ ”开头,而当有异常写人到日志中时, 异常信息不会按日志统一格式打印。multiline 提供了几个可以设置如何合并多 行的参数,比如说:
codec = > multiline {
pattern = > "^\[ "
negate = > true what = > "previous"
}
pattern 参数设置了一个正则表达式,代表的含义是以方括号“ [ ”开头的文 本。patterm 参数与 negate 参数共同决定什么的文本需要被合并, negate 参数 用于设置对 patterm 定义的正则表达式取反。所以上面定义这两个参数的含义就 是所有不满足“^\[ ”正则表达式的行都需要被合并,而合并到哪里则由参数 what 来决定。what 参数有 previous next 两个可选值,前者将需要合并行与前一 一个事件合并,而后者则会将需要合并行与后一个事件合并。
json 编解码器
json 文本的编解码器有两种,一种叫 json 编解码器,另一种叫 json_lines 编解码器。在输入时从 JSON 格式的数据中将消息解析出来生成事件,而在输 出时将事件编码为 JSON 格式的数据。如果 json 编解码器在解析 JSON 时出错, Logstash 会使用 plain 编解码器将 JSON 视为纯文件编入事件,同时会在事件 中添加_jsonparsefailure 标签。 json 编解码器只有一个参数 charset, 用于设置 JSON 数据字符集,默认为 UTF-8。json_ lines 编解码器也用于处理基于 JSON 的文本格式,但它处理的是一
种被称为 JSONLines 的特殊 JSON 格式。这种格式由多个独立的 JSON 行组成, 每一行都是有 效的 JSON 值。 json_lines 可用于存储每行一个 JSON 的结构化数据,适用于 unix 风格的 文本处理工具和 shell 管道。有关 JSON Lines 的相关说明请参考 JSON Lines
官方网站 http://jsonlines. org/
json_ lines 编解码器包括 charset delimiter 两个参数,前者用于设置 JSON 数据字符集,默认为 UTF-8; 而后者则用于设置 JSON Lines 格式中的行 分隔符。
序列化编解码器
在分布式应用中,为了将对象在网络中传输通常需要将对象转换为可传输的 文本或二进制字节流。这种将对象转换为文本或字节的过程就称为序列化,而将 文本或字节还原为对象的过程则称为反序列化。由于存在读取序列化数据格式的 需求,Logstash 也提供了两种针对不同序列化协议的编解码器 , 它们就是 avro 和 protobuf 。 Avro 最初是 Hadoop 的一个子项目,负责 Hadoop 中数据序列化与反序列 化,现在已经发展为 Apache 顶级开源项目。 Avro 需要通过 Schema 文件定义 对象格式,然后再依照Schema 文件定义做序列化和反序列化。 Logstash avro 编解码器也是基于 Schema 文件,所以在定义 avro 编解码器时必须要指定的参 数是 schema_uri, 用于定义 Schema 文件的存储路径。 Protobuf 是 Google 定义的另一种序列化协议, 与其他序列化协议相比 Protobuf 更小更快也更简单,所以在很多领域都得到了广泛应用。 Logstash 的 protobuf 编解码器默认并没有安装,需要使用“logstash-plugin install lgstash-codec-protobuf" 安装。 protobuf 编解码器有两个参数,一个是 class_ name 用于指定 . proto 文件中定义类的名称,另 - 一个是 include_ path 用于定 义.proto 文件的存储路径。
输入输出插件
Logstsh 管道可以配置多个输入插件,这可以将不同源头的数据整合起来做统 一处理。在分布式系统中,数据都分散在不同的容器或不同的物理机上,每份数 据往往又不完整,需要类似 Logtash 这样的工具将数据收集起来。比如在微服务 环境下,日志文件就分散在不同机器上,即使是单个请求的日志也有可能分散在 多台机器上。如果不将日志收集起来,就无法查看一个业务处理的完整日志。 Logstash 管道也可以配置多个输出插件,每个输出插件代表一种对数据处理 的业务需求。比如对日志数据存档就可以使用 s3 输出插件,将日志数据归档到 S3 存储服务上 ; 还可以使用 elasticsearch 输出插件,将数据索引到 Elasticsearch
中以便快速检索等。在业务系统创建之初,人们对于数据究竟会产生什么样的价 值并不清楚。但随着人们对于业务系统理解的深人,对数据处理的新需求就会进 发出来。面对新需求,只要为 Logstash 管道添加新的输出插件就能立即与新的 数据处理需求对接起来,而对已有数据处理业务又不会产生任何影响。到目前为 止,Logstash 对于常见的数据处理需求都可以很好的对接,这包括数据归档存 储、数据分析处理、数据监控报警等。 Logstash 官方提供的输入插件与输出插件都有 50 多种,而在这共计 100 多种 的插件中每一种插件又有不同的配置参数,全部都了解意义不大。这些插件基本 上都会成对出现,大多数输入插件也会在输出插件中出现。我们挑选几个有代表 性的来学习一下。
stdin 输入插件和 stdout 插件
两个最简单的插件,即 stdin 输入插件和 stdout 插件。这两个插件分别代表标 准输入和标准输出,也就是命令行控制台。由于它们比较简单,所以一般不需要 做任何配置就可以直接使用。 stdin 只有一组通用参数,这些参数不仅对 stdin 有效,对其他输入插件也有效。
 
 
同样的, stdout 也是只有通用参数,这些参数也是对所有输出插件都有效。
 
 
elasticsearch 插件
Elasticsearch 既可以作为 Logstash 的输入也可以作为输出,但在多数情况下 Elasticsearch 都是作为 Logstash 的输出使用。
elasticsearch 输出插件使用 hosts 参数设置连接 Elasticsearch 实例的地址, hosts 参数可以接收多个 Elasticsearch 实例地址, Logstash 在发送事件时会在 这些实例上做负载均衡。如果连接的 Elasticsearch Logstash 在同一台主机 且端口为 9200,那么这个参数可以省略。 elasticsearch 插件连接相关部分参数列表
 
elasticsearch 输出插件将 Logstash 事件转换为对 Elasticsearch 索引的操作, 默认情况下插件会将事件编人名称格式为“ logstash- %{+ YYYY. MM. dd} ”的 索引中,可使用 index 参数修改索引名称格式。 除了编入索引以外,elasticsearch 输出插件还支持根据 ID 删除文档、更新文 档等操作,具体可以通过 action 参数配置。 action 可选参数包括 index delete 、 create 和 update 几种,其中 index create 都用于向索引中编入文档,区别在 于 create 在文档存在时会报错,而 index 则会使用新文档替换原文档。 dele 和 upate 则用于删除和更新文档,所以在使用 delete update create 时需要通 过 document_ id 参数指定文档 ID 。此外, update 在更新时如果文档 ID 不存在, 那么可以使用 upsert 参数设置添加新文档的内容。例如 :
output{
elasticsearch {
document_id = > "% {message}"
action = > "update" upsert = > "{\"message\":\"id didn't exist\"}"
    }
}
message 属性的内容作为文档 ID 值,并根据这个 ID 值使用当前文档更新原 文档。如果文档不存在则使用 upsert 参数设置的内容添加文档, upsert 参数要 求为字符串类型,其中属性要使用双引号括起来。除了 upsert 以外,还可以将 doc_as_upsert 参数设置为 true ,则在文档不存在时会将当前文档添加到索引。elasticsearch 插件还有很多与 Elasticsearch 索引、模板、路由等相关的参数
elasticsearch 输出插件部分参数列表
 
Elasticsearch 作为 Logstash 输入源时, Logstash 默认会通过 DSL 从索引 "logstash-*" 中读取所有文档,一日读取完毕 Logstash 就会自动退出。输入插 件使用的 DSL 通过 query 参数设置,参数值与 Elasticsearch _search 接口参
数相同。
文件插件
面向文件的输入插件从文件中读取数据并转换为事件传入 Logstash 管道,而 面向文件的输出插件则将 Logstash 管道事件转换为文本写入到文件中。面向文 件的输入输出插件名称都是 file, 它们都需要通过 path 参数设置文件路径。 不同的是,文件输入插件的 path 参数类型是数组,所以可以指定组文件作为 输入源头。 而文件输出插件的 path 参数则为字符串,只能设置一个文件名称。此外,文 件输入插件的 path 参数只能是绝对路径而不能使用相对路径,并且在路径中可 使用“* ”和“ ** ”这样的通配符。 而文件输出插件则可以使用相对路径,并且还可以在路径中使用“%{} ”的形 式动态设置文件路径或名称。这也是文件输出插件形成滚动文件的方式,例如使 用“path=>/logs/log-%{+YYYY-MM-dd}.log ”配置输出插件就可以每日生成一个 文件。
 
事件属性
文件输入插件产生的输入事件中包含一个名为 path 的属性,它记录了事件实 际来自哪个文件。在配置文件输入插件时,如果在读取路径配置中使用了通配符 或使用数组指定了多个读取路径时,path 属性可以明确事件实际来源的文件。 换句话说,path 属性记录的是某个文件的具体路径和名称而不会包含通配符。 默认情况下,文件输入插件以一行结束标识一个输入事件,message 属性中 会包含换行符前面的所有内容。当然也可以通过将插件的编解码器设置为 multiline,将多行数据归为一个输入事件。文件输入插件默认也以换行符“ \n ”作 为行结束标识。
读取模式
文件输入插件默认会从文件结尾处读取文件的新行,这种模式被称为尾部读取 模式(Tail Mode) 。如果 Logstash 启动后被读取文件没有新行产生,则不会有新 的事件输出。 除了尾部读取模式以外,文件输入插件也可配置为从文件开头读取,这种模式 称为全部读取模式( Read Mode) 。也就是说,文件输入插件支持两种读取模式, 尾部读取模式和全部读取模式,可以通过设置文件输入插件的参数 mode 以修改 读取模式。 例如可以将示例中读取模式设置为 read, 这样只要被读取文件不为空, Logstash 启动后就会有输出 :
input {
file {
path = > "xxxx/xxxxx/logstash-plain. log"
mode = > "read"
   }
}
在尾部读取模式下,文件被看作是一个永不终止的内容流,所以 EOF EndofFile) 标识对于文件输入插件来说没有特别意义。如果使用过 Linux 中的 tail 命令,文 件输入插件的尾部读取模式与 tail -0F 极为相似。 尾部读取模式非常适合实时搬运日志文件数据,只要有新日志产生它就会将变化内容读取出来。而在全部读取模式下文件输入插件将每个文件视为具有有限行
的完整文件,如果读取到 EOF 就意味着文件已经结束,文件输入插件会关闭文 件并将其置于“未监视”状态以释放文件。
参数 file_ completed action 可以设置文件读取结束后的释放行为,可选值为 delete、 log log_ and_ delete, 默认行为是删除文件即 delete 。如果选择 log 或 log and _delete, 还需要使用 file_completed log_ path 参数指定一个日志文 件及其路径,文件输入插件会将已经读取完的文件及其路径写入到这个日志文件 中。对于 log_and_delete 来说,则会先写日志再将文件删除。需要特别注意的 是,文件输入插件在写这个日志文件时,并不负责对文件的滚动,所以该日志文 件可能会变得非常大。
多文件
path 参数配置的文件是多个时,文件输入插件会同时监控这些文件。当文 件大小发生了变化,文件输入插件会将这些文件激活并打开。 文件输入插件感知文件变化的方法是每隔 1 秒钟轮询所有被监控文件,这个时 间间隔由参数 stat_interval 控制。显然增加 stat_ interval 的值会减少访问文件 的次数,但会增加用户感知文件变化的时间延迟。 除了感知已知文件的变化以外,文件输入插件也会感知到新文件的加入。新加 入文件的感知时间间隔由 discover_interval 参数来控制,它设置的值是 stat_interval 的倍数,所以实际发现新文件的时间间隔是 discover. interval * stat interval。 默认情况下 discover_interval 15s, slat. inteval 1s, 所以发现 新文件的最大时间间隔为 15s。如果被监控文件变化非常频繁,可以将 stat_interval 值缩小以减少数据延迟。 在轮询被监控文件时,轮询文件的顺序也是有讲究的。在 Logstash 的早期版 本中,轮询的顺序由操作系统返回文件的顺序决定。 新版本中这个顺序由两个参数共同决定,一个是 file_sort_by 参数,定义根据 文件哪一个属性排序; 另一个是 file_sort direction 参数,定义文件轮询是按升序 还是按降序。 file_sort_by 有两个可选值 last_modified path, 前者按文件最后修改时间排 序,是默认值; 后者是按文件路径和名称排序。 file_sort_direction 也有两个可选 值,asc 代表升序, desc 代表降序,默认值为 asc 。所以在默认情况下,轮询 是按照文件最后修改时间的升序依次进行的,也就是最先修改的数据将会被优先 感知到并处理。 文件输入插件同时打开文件的数量也有上限,默认情况下文件输入插件可同时 打开文件的数量是 4095 个,这个值可以通过 max_open_files 参数来修改。设 置了同时打开文件的最大值,可以防止打开文件过多而影响系统性能或者将系统 拖垮。如果需要打开的文件数量很多,又不能将 max_open_files 设置过大,可 以使用 close_older 将长时间无变化的文件关闭以释放打开文件的数量空间。 close_ older 设置了文件未被读取的时间间隔,达到这个标准后文件即被关闭, 默认值为 1 小时。文件在关闭后如果又发生了变化,它将重新进入队列中等待打 开。由于在全部读取模式下文件读取完毕后就会被释放,所以 close_older 参数
仅对尾部读取模式有效。 文件输入插件在打开文件后,会按前面讲的顺序依次读取所有文件,直到读取 完所有文件。在默认情况下,它会先将一个文件需要处理的内容全部读取完再读 下一个文件。但这个行为可以通过更改 file_chunk_size file _chunk_count 来 修改,它可以使插件每次只读取文件一部分内容后就读取下一个文件,这对于快 速将全部文件的变化反馈给用户非常有用。 其中,file_hunk_size 用于设置每次读取数据块的大小,默认值为 32768 即 32kB; file_chunk_count 则用于设置处理每个文件时读取多少个数据块,默认值 为 4611686018427387903, 所以相当于读取没有上限。一般只需要将 file_chunk_ count 值缩小,而无需修改 file_ _chunk_ size 值。 除此之外,还有一个 start_position 参数,设定文件开始读取位置,仅对 tail
模式有效。 在配置项中如果遇到了与时长有关的,有一类类特殊的数据类型叫 string_duration,它用于以字符串的形式定义时间范围。 string_duration 的基本格 式为[number][string], 即由数字、空格和字符串组成,中间的空格可加也可以不 加,而字符串代表时间单位。例如 45s 45 s 都代表 45 秒, s 代表的时间单位 为秒。事件单位支持周(w week weeks )、天( d day days )、小时( h hour hours )、 分钟(m min minute minutes )、秒( s sec second seconds )、毫秒( ms msec msecs)、微秒( us usec usecs )。
文件输出插件
相对于文件输入插件来说,文件输出插件就简单多了。默认情况下,它会根据 path 参数指定的路径创建文件,并将事件转换为 JSON 格式写人文件的一行。 如果文件中已经有数据,则新事件会附加到文件结尾。当然也可以通过修改 write_ behavior 参数为 overwrite, 覆盖文件中已存在的数据。
更多插件
面向关系型数据库的插件
面向关系型数据库的插件用于从关系型数据库中读取或写入数据,它们的名 称是 jdbc 。 Logstash 官方只提供了 jdbc 输入插件,而输出插件则属于社区开发插件。 jdbc 输入插件可以定期执行 SQL 查询数据库,也可以只执行一次 SQL 。每 读入数据库表中一行会生成一个输入事件,行中每一列会成为事件的一个属性。 jdbc 输入插件可用于结构化数据的大数据分析和处理,可以将关系型数据库中的 数据传输到类似 Elasticsearch 这样的 NoSQL 数据库以方便海量数据检索或存 档,或传输给 Spark Storm 这样的大数据分析框架做实时分析处理。 JDBC 连接数据库需要指定 JDBC 驱动程序、 JDBC URL 以及数据库用户名和密 码, jdbc 输入插件也不例外。除了连接数据库,还要为 jdbc 输入插件定义要执 行的 SQL 语句。
面向消息中间件的插件
Logstash 虽然内置了队列对输入事件做缓冲,但面对瞬间突发流量时仍然存 在出错甚至崩溃的可能。同样地,如果 Logstash 给目标数据源发送数据量过大, 也存在着压垮目标数据源的可能。所以在一些流量比较大的互联网应用中,基本 上都会视情况在 Logstash 之前或之后部署分布式消息中间件,以达到削峰填谷、 保护应用的作用。除了削峰填谷,消息中间件还可以作为一种适配器来使用。有 些应用可以向消息中间件发送消息,但却没有 Logstash 的相关输入插件。这时就 可以让 Logstash 从消息中间件中订阅该应用的消息,以间接的方式从应用中获取 数据。Logstash 面向消息中间件的插件主要是 kafka redis rabbitmq 三个插件, stomp 和 jms 插件虽然也是基于消息的协议,但它们并未在 Logstash 的默认绑 定中,需要自行安装。
面向通信协议的插件
Logstash 面向通信协议的插件通过标准通信协议与外部数据源交互,支持包 括 TCP UDP HTTP IMAP 等广泛应用的协议。由于这些插件从通信协议层面 支持数据传输,可以支持基于这些协议对外提供服务的应用,因此极大地扩展了 Logstash 的应用范围。以 Elaticsearch 为例,它对外提供的 REST 接口基于 HTTP , 所以尽管 Logstash 提供了 elasticsearch 输入和输出插件,但依然可以通过 HTTP 相应的插件实现数据输入和输出的功能。
执行命令插件
据采集问题,但依然有可能存在一些特殊情况需要使用特定命令或脚本处理 数据。Logstash 提供了两个可执行命令或脚本的插件 exec pipe, 它们都同时具 有输入和输出插件。 exec 输入插件将执行命令的结果转换为事件传人 Logstash 管道,而 exec
出插件则针对每一个事件执行一条命令,所以它们都必须要通过 command 参数 指定要执行的命令。 pipe 插件基于操作系统管道机制实现数据的输入和输出,但正因为使用了管 道而不能在 Windows 系统中使用 pipe 插件。pipe 同时具备输入插件和输出插件。
开发测试插件
Logstash 提供了两种可以自动生成事件的输入插件,即 generator heartbeat 输入插件,可以使用它们测试配置是否正常或测试组件的性能指标。 generator 插件默认会不间断地生成输入事件,事件包含的文本内容为 “ Hello world!" 。事件的生成次数可由参数 count 设置,默认值 0 代表不限次数。 事件的文本内容可以通过 message lines 参数定义。 heartbeat 插件与 generator 插件类似,也是自动生成包含特定文本内容的输 入事件。不同的是,heartbeat 插件的输入事件会按定的时间间隔产生。 事件生
成的事件间隔默认值为 60s ,可使用 interval 参数修改。
过滤器插件
一个 Logstash 管道可以配置多个过滤器插件,每个过滤器插件的职责各不相 同。它们可以对原始数据做添加、删除、修改等基本的转换操作,也可以对原始 文本数据做结构化处理,还可以对数据做一致性校验、 清除错误数据等。这相 当于数据处理与分析领域中的数据清洗,是数据处理与分析中极为重要的一环。 多个过滤器会组装成过滤器的职责链,事件经过一个过滤器处理后会传递给下一 个过滤器,过滤器处理事件的顺序与它们在配置文件中的配置次序一致。Logstash 官方提供了 40 多种过滤器插件,我们会了解下常用插件。 各种过滤器插件有一些通用参数,这些参数对于比如 add_ field add_ tag 参数,它们可以在过滤器成功执行后向事件中添加属性或添加标签。而 remove. field 和 remove. _tag 参数则刚好相反,它们会在过滤器成功执行后删除属性或 标签。
过滤器通用参数
 
 
这些参数在各种过滤器中的含义基本相同。
 
全文数据结构化过滤器
全文数据是典型的非结构化数据。但有些全文数据具有一定的格式规范,它 们比较接近半结构化数据,但相比于半结构化数据又粗糙一些。 在这种类型的 文本中,比较典型的例子就是系统或应用输出的文本日志。这些文本日志往往都 是按一定 的次序包含时间、线程、日志级别、日志信息等内容,所以在处理上 非常适合使用正则表达式做解析,并从中提取出结构化数据以方便对数据做进一 步 分析。 Logstash 过滤器插件中, grok 过滤器和 dissect 过滤器都可以通过定义模式 文本中提取数据。不同的是 grok 过滤器使用的是正则表达式定义模式,而 dissect 过滤器则是使用“%{} ”的格式定义了一套独立的模式规则。从使用上来说, grok 过滤器由于使用了正则表达式而功能强大,但也使得它在处理文本时的性能比较 低; dissect 虽然功能简单,但性能更为出众,适用于文本格式规则比较简单的 文本。
grok 过滤器
grok 过滤器在 Logstash 过滤器插件中应该是最为常用的文本结构化过滤器, 对于一些中间件日志文本的处理来说,
grok 过滤器几乎是必须要选择的过滤器插 件。grok 过滤器根据一组预定义或自定义的模式去匹配文本,然后再将匹配的结
果提取出来存储在事件属性上,后续过滤器插件就可以在此基础上做进一步处理。 预定义模式 grok 过滤器预定义了大约 120 种模式,它们使用 - - 组由大写字母组成的模式 名称来惟一标识。常用的模式名称包括 NUMBER ( 数字 ) WORD ( 单词 ) 、SPACE (空 格) DATA( 任意字符 ) 等:
NUMBER
(?:% I BASE10NUM| ) 十进制数, BASE10NUM 的简写
BASEIONUM
(?<! [0-9. +-])(?>[ +-]?(?:(?:[0-9] +(?:\. [0-9] +)?) |(?:\.[0-9]+)))
十进制数,整型或浮点型数值
WORD
单词
SPACE 空格
NOTSPACE 非空格
DATA 任意字符 , 非贪婪模式匹配
GREEDYDATA 任意字符 , 贪婪模式匹配
TIMESTAMP_IS08601
IS08601 定义的日期格式,即 yyyy- MM-
dd'T'HH:mm:ss:SSSZZ
LOGLEVEL 日志级别
由于这些预定义的模式很多,大家可通过如下地址查看这些模式的列表和详 细定义:
https ://github.com/logstash-plugins/logstash-patterns-core/tree/master/patte
rns
如果使用 grok 过滤器预定义模式定义文本提取规则,需要遵从一定的语法 规则。具体来说,它们的基本语法格式为“% { SYNTAX: SEMANTIC} , 其中 SYNTAX 为模式名称,SEMANTIC 为存储匹配内容的事件属性名称。如果想匹配一段数字 并希望将匹配出来的数字存储到事件的 age 属性上,则按上述语法规则应该写为 "% { NUMBER:age}"。在这段提取规则中就使用到了前面的预定义模式 NUMBER
自定义模式
如果 grok 过滤器预定义的模式不能满足要求,用户也可以根据 grok 过滤器 指定的语法直接使用正则表达式定义模式。自定义模式的语法格式为“(?< 属性 名> 模式定义 ) ”,其中“ < 属性名 > ”指定了模式匹配后存储属性的名称,注意这 里的尖括号是语法的一部分故而不能省略。“< 属性名 > ”后面的“模式定义”代 表使用正则表达式定义的模式。例如,义邮政编码的模式为 6 位数字,并希望提
取后存到 postcode 属性上,则使用 grok 自定义模式表示的提取规则 为”(?<postcode >\d{6})”
match 参数
grok 过滤器最重要的一个参数是 match, 它接收一个由事件属性名称及其文 本提取规则为键值对的哈希结构。grok 过滤器会根据 match 中的键读取相应的 事件属性,然后再根据键对应的提取规则从事件属性中提取数据。下面通过一个 简单的例子来说明 match 参数的用法。 以 Logstash 默认日志的格式为例,Logstash 每条日志开头都包括三个方括号, 方括号中的内容依次为时间、日志级别、Logger 名称等,在这三个方括号后面 跟的是日志具体信息。具体格式可以到 Logstash 安装路径下的 logs 目录中查看 logstash- plain. log 文件,这里摘取其中几行为例 :
 
由于 Logstash 日志遵从一定的格式规范,所以如果使用 grok 过滤器的 match 参数定义提取规则,就可以将时间、日志级别、Logger 名称和日志内容提取出来。 提取规则如示例所示:
filter{
grok {
match = >{
message = >
"\[%{TIMESTAMP_ISO8601:time}\]\[%{LOGLEVEL:level}%{SPACE}\]\[%{NOTSPACE:lo
gger}%{SPACE}\]%{SPACE}%{GREEDYDATA:msg}"
          }
     }
}
在示例中, match 参数的类型为散列,其中只包含有一个条目。这个条目以 message 属性为键,而以对该属性的提取规则为值。在 message 属性的提取规则 中,使用了多个预定义模式。比如其中的“% {LOGLEVEL:level}" 就是使用 LOGLEVEL
预定义模式匹配文本,并将匹配结果添加到事件的 level 属性。 在默认情况下,grok 插件在模式匹配失败时会给事件打上 _ grokparsefailure 标签。除了 match 参数以外, grok 还有很多参数,大家可以自行查询相关网址。
dissect 过滤器
dissect 过滤器是另一种可以实现文本结构化的过滤器,它使用用户自定义的 分隔符切分文本,然后再将切分后的文本存储到事件属性上。 dissect 过滤器使用多个切分单元 (Dissection) 定义切分规则,切分单元之间可 以有一个或多个字符,这些字符就是切分文本的分隔符。定义一个切分单元的格 式为“%{ field}", 其中的 field 在一般情况下是事件的属性名称。 例如在“%{ field1}/% {field2}" 中共定义了两个切分单元,由于符号“ / ”位于 两个切分单元之间,所以将被认为是切分文本的分隔符。如果切分规则中包含有 三个以上的切分单元,则在切分规则中就可以指定多个分隔符了。
mapping 参数
dissect 过滤器使用 mapping 参数定义切分文本的方式, mapping 参数也是 哈希类型。与 match 参数类似, mapping 参数的键为需要切分的属性名称,而值 则为切分规则。下面以 Logstash 日志存档文件名称为例,说明如何使用 mapping 参数定义切分规则。Logstash 日志存档文件名称有着非常固定的格式,比如
 

假设输人事件的 message 属性保存的文本就是 Logstash 存档日志文件名称, 使用 dissect 过滤器做切分就可以定义如下 :
filter {
dissect{
mapping => {
message =>
"%{component}-%{log_type}-%{year}-%{month}-%{date}-%{index}.%{extension}.%{co
mpress}"
          }
      }
}
在示例中, message 属性定义的切分规则中就包含有两种分隔符“ - ”和“ . ”, dissect 过滤器会按分隔符的顺序依次切分文本。切分后的文本会存储到事件属性 上,在后续过滤器中,这些属性就可以参与其他处理了。 总的来看,dissect 过滤器虽然不及 grok 过滤器强大,但针对简单文本的处 理却也足够了。
处理半结构化文本
半结构化文本一般都有固定的格式要求,它们往往都有通用的格式规范,比 如 JSON XML CSV 等。同样通过可以解析半结构化文本的过滤器插件,它们同 样会将解析的结果存储在事件属性上。
json 过滤器
json 过滤器从属性中读取 JSON 字符串,然后按 JSON 语法解析后将 JSON 属 性添加到事件属性上。所以使用 json 插件有一个必须要设置的参数 source, 它是 用来指定插件从哪一个事件属性中读取 JSON 字符串,例如 :
filter{
json {source =>message”}
}
xml 过滤器
类似地, xml 过滤器用于解析 XML 格式的文本,过滤器读取 XML 原始文本 的事件属性由 source 参数配置, XML 解析结果存储的事件属性由 target 参数配 置。例如:
filter(
xml {
source => message
target => doc }
}
在示例中,配置的 xml 过滤器会从事件的 message 属性读取 XML 文本,然 后将文本解析后存储到 doc 属性上。 xml 过滤器在解析 XML 时会使用 XML 标签 名称作为事件属性名称,而将标签体的文本作为事件属性的值。但如果标签体中 嵌套了子标签或者标签本身还带有属性,那么事件的属性就会以散列类型代表这 个标签的解析结果。对于标签属性,它们将会以属性名称和值为键值对成为散列 结构的一个条目,而标签体中的非标签文本将会以 content 为键形成条目。比如 :
<root>
<student id="1">tom</student>
<grade>3</grade >
</root >
那么解析后就成为:
"doc" => {
"student" =>{
"content" => " tom",
" id"=>"1"
},
"grade" => "3 "
}
默认情况下, xml 过滤器为了防止同名标签覆盖问题,会将每个标签都解析 为数组类型。
csv 过滤器
CSV Comma Separated Values 的简写,即逗号分隔值。它是一种数据格式, 以这种格式保存的文件通常扩展名为 CSV 。这种格式以纯文本形式表示表格数据, 数据的每一行都是一条记录,每个记录又由一个或多个字段组成,用逗号分隔。 一些关系型数据库的客户端就提供了导出 CSV 格式数据的功能 csv 过滤器就是根据这种格式将它们解析出来,并将解析结果存储到不同的
属性名上。 默认情况下,属性名由 csv 过滤器自动生成,名称格式类似于 column1 、 column2; 属性名也可以通过 columns 参数以数组的形式定义。此外,在 CSV 格 式中第一行也可以用于表示列名,如示例 14-12 中第行所示。如果希望使用 CSV 文本中定义的列名,则需要通过 autodetect_column_names 参数显示地设置首行 为列名。
kv 过滤器
kv 过滤器插件用于解析格式为 "key = value" 的键值对,多个键值对可以使用 空格连接起来,使用 field _split 或 field_split_patterm 可以定制连接键值对的分 隔符。 kv 过滤器默认会从 message 属性中取值并解析,解析后的结果会存储在 事件的根元素上。例如"usermname =root&password = root" 的分隔符为“ &" ,比 如:
message = >"username = root&password = root "
则:
filter {
kv {field_split => "&"}
}
事件聚集过滤器
Logstash 提供的 aggregate 过滤器可以将多个输人事件整合到一起,形成一 个新的、带有总结性质的输人事件。例如,假设某个业务请求由多个服务处理, 每个服务都会生成一些与请求相关的数据。如果需要从这些数据中提取部分信息 做整合就可以使用 aggregate 过滤器,比如从每个服务的日志中提取单个服务处 理时间以计算整个请求处理了多少时间。 为了将相关事件整合到一起,aggregate 过滤器需要解决两个问题。首先, 由于需要将一组输人事件整合起来做处理,所以 aggregate 过滤器需要有办法区 分输人事件的相关性; 其次,由于需要跨事件做数据处理和运算,所以 aggregate 过滤器需要一个能在多个输人事件之间共享数据的存储空间。 aggregate 过滤器通过任务的概念组合相关事件,并通过 map 对象在事件之 间共享数据。

logstash分析完成,下一篇我们分析ELK实战,敬请期待。

 

Logstash是一个开源工具,用于收集、过滤、转换和发送日志和事件数据。它是ELK堆栈(ElasticsearchLogstash和Kibana)的一部分,被广泛用于实时日志分析和数据可视化。 Logstash的工作原理可以分为三个主要阶段:输入、过滤和输出。 在输入阶段,Logstash从各种来源收集数据,包括文件、网络中的日志、消息队列等。它提供了多个输入插件,可以根据需要选择。一旦数据被输入到Logstash,它会根据特定的数据格式进行解析,以便能够处理和转换。 在过滤阶段,Logstash可以对数据进行各种操作,例如分割字段、添加或删除字段、转换数据类型、移除无用的数据等。这是一个可选的步骤,可以根据实际需求来进行配置。Logstash提供了许多内置的过滤器,还支持自定义过滤器插件。 在输出阶段,Logstash将过滤后的数据发送到指定的目标,最常见的是将数据发送到Elasticsearch进行索引和存储。此外,Logstash还支持将数据输出到其他目标,如消息队列、文件、数据库等。用户可以根据需求配置适当的输出插件。 Logstash还提供了一些额外的功能,例如数据缓冲和批处理,以优化性能和处理大量数据。它还具有容错机制,可以处理故障和错误,确保数据的可靠传输和处理。 总之,Logstash原理是通过输入阶段收集数据,然后在过滤阶段处理和转换数据,并在输出阶段将数据发送到指定的目标。它的灵活性和可扩展性使得它成为处理和分析日志数据的有效工具。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值