网站维护一般做什么,wordpress友情链接做导航,网页设计基础实训,怎么做网页文件打开别的网站一、什么是LogStash
LogStash 是一个类似实时流水线的开源数据传输引擎#xff0c;它像一个两头连接不同数据源的数据传输管道#xff0c;将数据实时地从一个数据源传输到另一个数据源中。在数据传输的过程中#xff0c;LogStash 还可以对数据进行清洗、加工和整理#xf…一、什么是LogStash
LogStash 是一个类似实时流水线的开源数据传输引擎它像一个两头连接不同数据源的数据传输管道将数据实时地从一个数据源传输到另一个数据源中。在数据传输的过程中LogStash 还可以对数据进行清洗、加工和整理使数据在到达目的地时直接可用或接近可用为更复杂的数据分析、处理以及可视化做准备。
既然需要将数据搬运到指定的地点为什么不在数据产生时就将数据写到需要的地方呢?这个问题可以从以下几个方面理解。首先许多数据在产生时并不支持直接写入到除本地文件以外的其他数据源。比如大多数第三方软件在运行中产生的日志都以文本形式写到本地文件中。其次在分布式环境下许多数据都分散在不同容器甚至不同机器上而在处理这些数据时往往需要将数据收集到一起统一处理。 最后即使软件支持将数据写入到指定的地点但随着人们对数据理解的深人和新技术的诞生又会有新的数据分析需求出现总会有一些接入需来是原生软件 无法满足的。综上LogStash 的核心价值就在于它将业务系统与数据处现系统隔离开来屏蔽了各自系统变化对彼此的影响使系统之间的依赖降低并可独自进化发展。
LogStash 可以从多个数据源提取数据然后再清洗过滤并发送到指定的目标数据源。目标数据源也可以是多个而且只要修改 LogStash 管道配置就可以轻松扩展数据的源头和目标。这在实际应用中非常有价值尤其是在提取或发送的数据源发生变更时更为明显。比如原来只将数据提取到 Elasticsearch 中做检索但现在需要将它们同时传给 Spark 做实时分析。如果事先没有使用 LogStash 就必须设计新代码向 Spark 发送数据而如果预先使用了 LogStash 则只需要在管道配置中添加新的输出配置。这极大增强了数据传输的灵活性。
话外音 由上面描述可知LogStash是为了解决分布式业务场景中不同的服务之间产生的日志数据如何采集而提出的解决方案。为了解决此问题LogStash具备的能力如下:
采用流水线和管道模式让数据流从端到端流动。(如何实现的这种方式需要研究)支持多数据源。可以进行数据的清洗加工和整理功能。 LogStash是将业务系统和日志采集做了隔离拆分因为采集逻辑 可能千变万化所以将其交给LogStash处理业务系统无需关注日志采集的处理逻辑。
二、 体系结构
Logstash 数据传输管道所具备的流水线特征体现在数据传输过程分为三个阶段–输入、过滤和输出。这三个阶段按顺序依次相连像一个加工数据的流水线。 在实现上它们分别由三种类型的插件实现即输入插件、过滤器插件和输出插件并可通过修改配置文件实现快速插拔。除了这三种类型的插件以外还有种称为编解码器 (Codec) 的插件。编解码器插件用于在数据进人和离开管道时对数据做解码和编码所以它一般都是与具体的输入插件或输出插件结合起来使用。
事件(Event) 是 Logstash 中另一个比较重要的概念 它是对 Logstash 处理数据的一种面向对象的抽象。如果将 Logstash 比喻为管道那么事件就是流淌在管道中的水流。事件由输入插件在读入数据时产生不同输入插件产生事件的属性并不完全相同但其中一定会包含有读入的原始数据。过滤器插件会对这些事件做进步处理 处理的方式主要体现在对事件属性的访问、添加和修改。最后输出插件会将事件转换为目标数据源的数据格式并将它们存储到目标数据源中。
在 Logstash 管道中每个输入插件都是在独立的线程中读取数据并产生事件。但输入插件并不会将事件直接传递给过滤器插件或输出插件而是将事件写入到一个队列中。队列可以是基于内存的也可以是基于硬盘的可持久化队列。Logstash 管道会预先生成一组工作线程这些线程会从队列中取出事件并在过滤器中处理然后再通过输出插件将事件输出。事件队列可以协调输入插件与过滤器插件、输出插件的处理能力使得 Logstash 具备了一定的消峰填谷能力。
除了输入插件使用事件队列与过滤器插件、输出插件交互以外Logstash 还在输出插件与目标数据源之间提供了一个死信队列(Dead Letter Queue)。死信队列会在目标数据源没有成功接收到数据时将失败的事件写人到队列中以供后续做进步处理。 话外音:
所谓的流水线特性就是数据经过了输入–过滤器–输出的流水线过程进入了另一端。基于插件化开发输入过滤器输出都是插件可以快速可插拔。(设计理念研究)。所谓的事件就是Logstash内部定义的一种统一的数据规范这样方便不同的插件统一处理。事件队列和死信队列设计的初衷(待研究)
2.1 插件
插件(Plugin)通过简单的配置就可接入系统并增强系统功能。Logstash 提供了丰富的输入、过滤器、输出和编解码器插件它们也都是通过配置接入系统并增强 Logstash 在某一方面的功能。 输入插件的作用是使数据进入管道并生成数据传输事件过滤器插件则对进入管道的事件进行修改、清洗等预处理而输出插件则将过滤器处理好的事件发送到目标数据源。输入插件和输出插件都可以使用编解码器在数据进入或退出管道时对数据进行编码或解码使数据以用户期望的格式进入或退出管道。 插件开发都很便捷一般都会提供统一接口作为开发框架开发人员只要遵从接口规范并编写逻辑就可以开发出新的插件。Logstash 插件使用 Ruby 语言开发。
Logstash提供了一条插件管理的命令 logstash-plugin,可以用于查看、安装、更新或删除插件。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 哈希类型的初始化格式。
话外音 插件的特点: 可插拔、命令化安装、默认插件和手动安装插件。 按插件类型划分: 输入插件: 生成传输事件 过滤器插件: 清晰、修改数据 输出插件: 发送到目标数据源。
2.2 事件
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 内置对象访问、修改或者删除事件属性。
2.3 队列
在互联网时代许多活动或突发事件会导致应用访问量在某一时间点瞬间呈几何式增长。在这种情况下应用产生的数据也会在瞬间爆发而类似 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 为此专门提供了一种死信队列输入插件它可以将死信队列中的事件读取出来并传输至另一个管道中处理。
2.4 管道配置
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 { ….. }插件参数的格式与插件本身的配置在格式上有些相同但又有着比较明显的区别。插件配置在插件名称与大括号之间是空格而插件参数则是使用“”关联起来的键值对。其中键是插件参数名称而值就是参数值。这种格式与 Ruby 哈希类型的初始化一样所以本质上来说每个插件的配置都是对 Ruby 哈希类型的初始化。
多管道配置 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 中完全一致它还可以使用配置队列和死信队列的参数只是这些参数都只对当前管道有效。
(这种管道思想都在哪里使用过体会什么场景使用管道思想以及如何实现管道思想。)
2.5 编解码器插件
在 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{codecline}
}output{stdout{codecplain{formatThe message is % {[message]}\nIts
from %{[host]}\n}}
}在示例中Logstash 在标准输入(即命令行)等待输入并将输入内容按format参数定义的格式以两行打印在标准输出中。
line 编解码器 以行为单位对文本数据进行解码时每-行都有可能成为一个独立事件;而在编码时每个事件输出结尾都会添加换行符。以行为单位的编解码器有 line 和muliline 两种前者以单行为输入事件而后者则根据一定条件将多行组装成一个事件。
multiline 编解码器也是以行为编解码的单元但在它编解码的事件中可能会包含一行也有可能会包含多行文本。multiline 编解码器对于处理日志中出现异常信息时非常有用它能将异常合并到同一个日志事件中。例如在下面中所示的一段日志文本 从是一个 Java 异常打印出来的堆栈信息在逻辑上它们都应该归属于 ERROR 日志: 一般来说正常日志都以方括号“[”开头而当有异常写人到日志中时异常信息不会按日志统一格式打印。multiline 提供了几个可以设置如何合并多行的参数比如说:
codecmultiline{pattern^\[ negatetruewhatprevious
}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 文件的存储路径。
2.6 输入输出插件
Logstsh 管道可以配置多个输入插件这可以将不同源头的数据整合起来做统一处理。在分布式系统中数据都分散在不同的容器或不同的物理机上每份数据往往又不完整需要类似 Logtash 这样的工具将数据收集起来。比如在微服务环境下日志文件就分散在不同机器上即使是单个请求的日志也有可能分散在多台机器上。如果不将日志收集起来就无法查看一个业务处理的完整日志。
Logstash 管道也可以配置多个输出插件每个输出插件代表一种对数据处理的业务需求。比如对日志数据存档就可以使用 s3 输出插件将日志数据归档到S3 存储服务上;还可以使用 elasticsearch 输出插件将数据索引到 Elasticsearch中以便快速检索等。在业务系统创建之初人们对于数据究竟会产生什么样的价值并不清楚。但随着人们对于业务系统理解的深人对数据处理的新需求就会进发出来。面对新需求只要为 Logstash 管道添加新的输出插件就能立即与新的数据处理需求对接起来而对已有数据处理业务又不会产生任何影响。到目前为止Logstash 对于常见的数据处理需求都可以很好的对接这包括数据归档存储、数据分析处理、数据监控报警等。
Logstash 管道也可以配置多个输出插件每个输出插件代表一种对数据处理的业务需求。比如对日志数据存档就可以使用 s3 输出插件将日志数据归档到S3 存储服务上;还可以使用 elasticsearch 输出插件将数据索引到 Elasticsearch中以便快速检索等。在业务系统创建之初人们对于数据究竟会产生什么样的价值并不清楚。但随着人们对于业务系统理解的深人对数据处理的新需求就会进发出来。面对新需求只要为 Logstash 管道添加新的输出插件就能立即与新的数据处理需求对接起来而对已有数据处理业务又不会产生任何影响。到目前为止Logstash 对于常见的数据处理需求都可以很好的对接这包括数据归档存储、数据分析处理、数据监控报警等。
stdin 输入插件和 stdout 插件
两个最简单的插件即 stdin 输入插件和 stdout 插件。这两个插件分别代表标准输入和标准输出也就是命令行控制台。由于它们比较简单所以一般不需要做任何配置就可以直接使用。
stdin 只有一组通用参数这些参数不仅对 stdin 有效对其他输入插件也有效。 同样的stdout 也是只有通用参数这些参数也是对所有输出插件都有效。
elasticsearch 插件
Elasticsearch 既可以作为 Logstash 的输入也可以作为输出但在多数情况下Elasticsearch 都是作为 Logstash 的输出使用。 elasticsearch 输出插件使用 hosts 参数设置连接 Elasticsearch 实例的地址hosts 参数可以接收多个 Elasticsearch 实例地址Logstash 在发送事件时会在这些实例上做负载均衡。如果连接的 Elasticsearch 与 Logstash 在同一台主机且端口为 9200那么这个参数可以省略。
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}actionupdateupsert{\message\:\id didnt exist\}}
}message 属性的内容作为文档 ID 值并根据这个 ID 值使用当前文档更新原文档。如果文档不存在则使用 upsert 参数设置的内容添加文档upsert 参数要求为字符串类型其中属性要使用双引号括起来。除了 upsert 以外还可以将doc_as_upsert 参数设置为 true则在文档不存在时会将当前文档添加到索引。elasticsearch 插件还有很多与 Elasticsearch 索引、模板、路由等相关的参数。
文件插件
面向文件的输入插件从文件中读取数据并转换为事件传入 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,覆盖文件中已存在的数据。
2.7 更多插件
面向关系型数据库的插件 面向关系型数据库的插件用于从关系型数据库中读取或写入数据它们的名称是 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相应的插件实现数据输入和输出的功能。
2.8 过滤器插件
一个 Logstash 管道可以配置多个过滤器插件每个过滤器插件的职责各不相同。它们可以对原始数据做添加、删除、修改等基本的转换操作也可以对原始文本数据做结构化处理还可以对数据做一致性校验、 清除错误数据等。这相当于数据处理与分析领域中的数据清洗是数据处理与分析中极为重要的一环。多个过滤器会组装成过滤器的职责链事件经过一个过滤器处理后会传递给下一个过滤器过滤器处理事件的顺序与它们在配置文件中的配置次序一致。
Logstash 官方提供了 40 多种过滤器插件我们会了解下常用插件。
各种过滤器插件有一些通用参数这些参数对于比如 add_ field 和 add_ tag参数它们可以在过滤器成功执行后向事件中添加属性或添加标签。而 remove. field 和 remove. _tag 参数则刚好相反它们会在过滤器成功执行后删除属性或标签。
2.8.1 全文数据结构化过滤器
全文数据是典型的非结构化数据。但有些全文数据具有一定的格式规范它们比较接近半结构化数据但相比于半结构化数据又粗糙一些。 在这种类型的文本中比较典型的例子就是系统或应用输出的文本日志。这些文本日志往往都是按一定 的次序包含时间、线程、日志级别、日志信息等内容所以在处理上非常适合使用正则表达式做解析并从中提取出结构化数据以方便对数据做进一步 分析。 Logstash 过滤器插件中grok 过滤器和 dissect 过滤器都可以通过定义模式文本中提取数据。不同的是 grok 过滤器使用的是正则表达式定义模式而 dissect过滤器则是使用“%{}”的格式定义了一套独立的模式规则。从使用上来说grok过滤器由于使用了正则表达式而功能强大但也使得它在处理文本时的性能比较低;而 dissect 虽然功能简单但性能更为出众适用于文本格式规则比较简单的文本。 grok 过滤器 grok 过滤器在 Logstash 过滤器插件中应该是最为常用的文本结构化过滤器对于一些中间件日志文本的处理来说grok 过滤器几乎是必须要选择的过滤器插件。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 过滤器强大但针对简单文本的处理却也足够了。
2.8.2 处理半结构化文本
半结构化文本一般都有固定的格式要求它们往往都有通用的格式规范比如 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 id1tom/student
grade3/grade
/root 那么解析后就成为
doc { student { content tom, id1
},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 rootpassword root的分隔符为“比如
message username rootpassword root 则:
filter {
kv {field_split }
}2.8.3 事件聚集过滤器
Logstash 提供的 aggregate 过滤器可以将多个输人事件整合到一起形成一个新的、带有总结性质的输人事件。例如假设某个业务请求由多个服务处理每个服务都会生成一些与请求相关的数据。如果需要从这些数据中提取部分信息做整合就可以使用 aggregate 过滤器比如从每个服务的日志中提取单个服务处理时间以计算整个请求处理了多少时间。 为了将相关事件整合到一起aggregate 过滤器需要解决两个问题。首先由于需要将一组输人事件整合起来做处理所以 aggregate 过滤器需要有办法区分输人事件的相关性;其次由于需要跨事件做数据处理和运算所以 aggregate过滤器需要一个能在多个输人事件之间共享数据的存储空间。 aggregate 过滤器通过任务的概念组合相关事件并通过 map 对象在事件之间共享数据。