Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

23.4. 在 Rsyslog 中使用队列

队列用于在 rsyslog 组件之间传递内容,大部分是 syslog 消息。利用队列,rsyslog 可以同时处理多个消息,并一次性对单个消息应用多个操作。rsyslog 中的数据流可以说明如下:

图 23.1. Rsyslog 中的消息流

Rsyslog 中的消息流

每当 rsyslog 收到消息时,它会将此消息传递到预处理器,然后将它放入 主消息队列。等待那里的消息被降序并传递到 规则处理器

规则处理器是分析和过滤引擎。此处应用 /etc/rsyslog.conf 中定义的规则。根据这些规则,规则处理器将评估要执行的操作。每个操作都有自己的操作队列。消息通过此队列传递到创建最终输出的对应操作处理器。请注意,此时可在一条消息上同时运行多个操作。为此,消息会重复并传递给多个操作处理器。

每个操作只能有一个队列。根据配置,可以在无需操作排队的情况下将消息发送到操作处理器。这是直接队列的行为 (请参见下文)。如果输出操作失败,操作处理器会通知操作队列,然后重新取一个未处理的元素,并在某一时间间隔后再次尝试该操作。

总之,队列在 rsyslog 中有两个位置:作为单个 主消息队列 在规则处理器前面,还是在不同类型的输出操作的前面作为 操作队列。队列提供两个主要优势,它们都会导致消息处理性能提高:

  • 它们充当在 rsyslog结构中 分离 生产者和消费者的缓冲
  • 它们允许并行化对消息执行的操作

此外,也可使用多个 指令配置队列,以便为您的系统提供最佳性能。以下小节中介绍了这些配置选项。

警告

如果输出插件无法发送消息,它将存储在前面的消息队列中。如果队列填满,则输入块直到其不再完整为止。这将阻止新消息通过被阻止的队列记录。如果没有单独的操作队列,这可能会产生严重后果,例如防止 SSH 记录,进而可以阻止 SSH 访问。因此,建议将专用的操作队列用于通过网络或数据库转发的输出。

23.4.1. 定义队列

根据消息的存储位置,有多种类型的队列:直接、内存中、磁盘 和磁盘辅助内存中队列使用最广。您可以为主消息队列选择这些类型之一,也可以选择用于操作队列。在 /etc/rsyslog.conf 中添加以下内容:

object(queue.type=”queue_type”)

通过添加此项,您可以为以下内容应用设置:

  • 主消息队列:将 对象 替换为 main_queue
  • 操作队列:将 object 替换为 操作
  • ruleset:将 对象 替换为 ruleet

使用 直接链接列表固定阵列( 内存中队列)或 磁盘 之一替换 queue_type

主消息队列的默认设置是 FixedArray 队列,限制为 10,000 个消息。操作队列默认设置为直接队列。

直接队列

对于许多简单的操作,如将输出写入本地文件时,不需要在操作前构建队列。为了避免排队,请使用:

object(queue.type=”Direct”)

object 替换为 main_queue操作规则集,以将此选项分别用于主消息队列、操作队列或规则集。使用直接队列时,消息会直接直接从制作者传递至消费者。

磁盘队列

磁盘队列严格将消息存储在硬盘驱动器中,这使其高度可靠,同时也是所有可能的队列模式中最慢的消息。此模式可用于防止丢失高度重要的日志数据。但是,大多数用例中不建议使用磁盘队列。要设置磁盘队列,请在 /etc/rsyslog.conf 中输入以下内容:

object(queue.type=”Disk”)

object 替换为 main_queue操作规则集,以将此选项分别用于主消息队列、操作队列或规则集。可使用以下配置指令修改队列的默认大小:

object(queue.size=”size”)

其中 size 代表磁盘队列部分的指定大小。定义的大小限制不受限制,rsyslog 始终 会编写一个完整的队列条目,即使它违反了大小限制。磁盘队列的每个部分都与单个文件匹配。这些文件的命名指令如下:

object(queue.filename=”name”)

这会为文件设置一个名称前缀,后跟一个从 1 开始并递增每个文件的 7 位数字。

object(queue.maxfilesize=”size”)

磁盘队列以部分形式编写,默认大小为 1 MB。指定要使用其他值的大小

内存中队列

使用内存中队列时,requeued 消息保存在内存中,这使得进程变得非常快速。如果计算机重启或关机,则排队的数据将丢失。但是,您可以使用 操作(queue.saveonshutdown="on") 设置在关闭前保存数据。内存队列有两种类型:

  • FixedArray queue - 主消息队列的默认模式,限制为 10,000 个元素。这种类型的队列使用固定的预分配的阵列,该阵列包含指向队列元素的指针。由于这些指示符,即使队列为空,也会消耗一定量的内存。但是,FixedArray 提供了最佳的运行时性能,并在您期望相对较少的排队消息和高性能时是最佳的。
  • LinkedList 队列 - 在这里,所有结构都在链接列表中动态分配,因此内存仅在需要时分配。LinkedList 队列处理偶尔的消息突发性。

通常情况下,当有疑问时使用 LinkedList 队列。与 FixedArray 相比,它会消耗较少的内存并降低处理开销。

使用以下语法配置内存队列:

object(queue.type=”LinkedList”)
object(queue.type=”FixedArray”)

object 替换为 main_queue操作规则集,以将此选项分别用于主消息队列、操作队列或规则集。

磁盘辅助内存中队列

磁盘和内存中队列都有其优势,而 rsyslog 则允许您将其组合 到磁盘辅助内存中队列中。为此,请配置普通内存中队列,然后将 queue.filename="file_name" 指令添加到其块中,以定义磁盘协助的文件名。然后,这个队列变为 diskassisted,这意味着它将内存队列与磁盘队列相结合,从而协同工作。

如果内存中队列已满或者需要在关机后保留,则激活磁盘队列。使用磁盘辅助队列,您可以同时设置特定于磁盘和内存的特定配置参数。这种队列或许是最常用的,对于潜在的长时间运行且不可靠的操作特别有用。

要指定磁盘辅助内存队列的功能,请使用所谓的水位线:

object(queue.highwatermark=”number”)
object(queue.lowwatermark=”number”)

object 替换为 main_queue操作规则集,以将此选项分别用于主消息队列、操作队列或规则集。将 number 替换为一组 enqueued 消息。当内存中队列达到高水位线定义的数量时,它开始将消息写入磁盘并继续,直到内存中队列大小下降到使用低水位线定义的数字。正确设置水位线可最大程度减少不必要的磁盘写入,但也为消息突发保留内存空间,因为写入磁盘文件非常长。因此,高水位线必须小于通过 queue.size 设置的完整队列容量。高水位线与总体队列大小之间的区别在于为消息突发保留的备用内存缓冲区。另一方面,将高水位线设置得过低将会带来不必要的磁盘帮助。

例 23.12. 可靠将日志消息转发至服务器

rsyslog 通常用于维护集中式日志记录系统,其中日志消息通过网络转发到服务器。为了避免服务器不可用时消息丢失,建议为转发操作配置操作队列。这样,发送失败的消息会存储在本地,直到服务器再次可访问为止。请注意,此类队列无法用于使用 UDP 协议的连接。

转发到单一服务器

假设任务是将日志消息从系统转发到主机名为 example.com 的服务器,并且配置操作队列以缓冲消息(以防服务器中断)。要做到这一点,请执行以下步骤:

  1. /etc/rsyslog.conf 中使用 以下配置,或在 /etc/rsyslog.d/ 目录中创建包含以下内容的文件:

    . action(type=”omfwd”
    queue.type=”LinkedList”
    queue.filename=”example_fwd”
    action.resumeRetryCount="-1"
    queue.saveonshutdown="on"
    Target="example.com" Port="6514" Protocol="tcp")

    其中:

    • queue.type 启用 LinkedList 内存中队列,
    • queue.filename 定义磁盘存储,在这种情况下,备份文件在 /var/lib/rsyslog/ 目录中创建,前缀为 example_fwd
    • action.resumeRetryCount= "-1" 设置阻止 rsyslog 在重试连接时丢弃消息(如果服务器没有响应)
    • 如果 rsyslog 关闭,启用的 queue.saveonshutdown 可保存内存中数据。
    • 最后一行使用可靠的 TCP 发送将所有收到的消息转发到日志记录服务器,端口规格是可选的。

      使用上述配置时,如果远程服务器无法访问,rsyslog 将消息保留在内存中。只有在 rsyslog 用尽配置的内存队列空间或需要关闭时,才会在磁盘上创建文件,这将提高系统性能。

转发到多个服务器

将日志信息转发到多个服务器的过程与前面的步骤类似:

  1. 每个目标服务器都需要独立的转发规则、操作队列规格和磁盘上的备份文件。例如,在 /etc/rsyslog.conf 中使用 以下配置,或在 /etc/rsyslog.d/ 目录中创建包含以下内容的文件:

    . action(type=”omfwd”
        queue.type=”LinkedList”
        queue.filename=”example_fwd1”
        action.resumeRetryCount="-1"
        queue.saveonshutdown="on"
        Target="example1.com" Protocol="tcp")
    . action(type=”omfwd”
        queue.type=”LinkedList”
        queue.filename=”example_fwd2”
        action.resumeRetryCount="-1"
        queue.saveonshutdown="on"
        Target="example2.com" Protocol="tcp")

23.4.2. 为 rsyslog 日志文件创建新目录

rsyslog 作为 syslogd 守护进程运行,并由 SELinux 管理。因此,rsyslog 需要写入到的所有文件都必须具有相应的 SELinux 文件上下文。

创建新工作目录

  1. 如果需要使用不同的目录存储工作文件,请按如下所示创建一个目录:

    ~]# mkdir /rsyslog
  2. 安装工具来管理 SELinux 策略:

    ~]# yum install policycoreutils-python
  3. 将 SELinux 目录上下文类型设置为与 /var/lib/rsyslog/ 目录相同:

    ~]# semanage fcontext -a -t syslogd_var_lib_t /rsyslog
  4. 应用 SELinux 上下文:

    ~]# restorecon -R -v /rsyslog
    restorecon reset /rsyslog context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:syslogd_var_lib_t:s0
  5. 如果需要,请按如下所示检查 SELinux 上下文:

    ~]# ls -Zd /rsyslog
    drwxr-xr-x. root root system_u:object_r:syslogd_var_lib_t:s0  /rsyslog
  6. 根据需要创建子目录。例如:

    ~]# mkdir /rsyslog/work/

    将使用与父目录相同的 SELinux 上下文创建子目录。

  7. /etc/rsyslog.conf 立即添加以下行才能生效:

    global(workDirectory=”/rsyslog/work”)

    此设置将保持有效,直到在解析配置文件时遇到下一个 WorkDirectory 指令。

23.4.3. 管理队列

可以进一步配置所有类型的队列,以符合您的要求。您可以使用多个指令来修改操作队列和主消息队列。目前,可用的队列参数超过 20 个,请参阅 “在线文档”一节。其中一些设置通常使用,另一些(如 worker 线程管理)提供对队列行为的更紧密控制,并保留给高级用户。使用高级设置,您可以优化 rsyslog的性能、调度排队或修改系统关闭时队列的行为。

限制队列大小

您可以使用以下设置限制队列可以包含的信息数量:

object(queue.highwatermark=”number”)

object 替换为 main_queue操作规则集,以将此选项分别用于主消息队列、操作队列或规则集。将 number 替换为一组 enqueued 消息。您只能将队列大小设置为消息数,而不是其实际内存大小。默认队列大小为主消息队列和规则集队列的 10,000 个消息,而 1000 则表示操作队列。

默认情况下,磁盘支持的队列没有限制,且无法使用这个指令进行限制,但您可以使用以下设置来为它们保留物理磁盘空间(以字节为单位):

object(queue.maxdiskspace=”number”)

使用 main_queueaction 或 rules et 替换 object。当按数字指定的大小限制被命中时,消息会被丢弃,直到 dequeued 消息释放足够数量的空间。

丢弃消息

当队列到达特定数量的消息时,您可以丢弃不太重要的消息,以便在队列中为优先级较高的条目节省空间。启动丢弃过程的阈值可使用所谓的 discard 标记来设置

object(queue.discardmark=”number”)

使用 MainMsg 或 Action 替换 object ,以 分别将此选项用于主消息队列或操作队列。此处,number 代表开始丢弃过程时必须要处于队列中的多个消息。要定义要丢弃的信息,请使用:

object(queue.discardseverity=”number”)

number 替换为以下对应优先级之一: 7 (debug)、6 (info)、5 (通知)、4( 警告)、3 (err)、2( crit)、1 (证书)或 0 (emerg)。使用此设置时,在到达丢弃标记后,将立即从队列中删除优先级低于定义的新传入和排队消息。

使用时间戳

您可以将 rsyslog 配置为在特定时间段内处理队列。例如,您可以使用此选项将一些处理转移到非高峰时段。要定义时间段,请使用以下语法:

object(queue.dequeuetimebegin=”hour”)
object(queue.dequeuetimeend=”hour”)

通过小时,您可以指定绑定时间段的小时。使用 24 小时格式(无分钟)。

配置工作程序线程

worker 线程在 enqueued 消息上执行指定的操作。例如,在主消息队列中,worker 任务是将过滤器逻辑应用到每一传入消息,并将它们排队到相关的操作队列。当消息到达时,会自动启动 worker 线程。当消息数量达到特定数字时,将打开另一个 worker 线程。要指定这个号码,请使用:

object(queue.workerthreadminimummessages=”number”)

number 替换为将触发补充工作线程的消息。例如,当数字设置为 100 时,当到达 100 条消息时会启动一个新的 worker 线程。当到达 200 条信息时,第三个 worker 线程启动,以此类推。但是,并行运行的太多工作线程会变得无效,因此您可以使用以下方法限制它们的最大数量:

object(queue.workerthreads=”number”)

其中,数字表示可以并行运行的最大工作线程数。对于主消息队列,默认限制为 1 线程。启动工作线程后,它将持续运行,直到出现不活跃的超时为止。要设置超时长度,请输入:

object(queue.timeoutworkerthreadshutdown=”time”)

time 替换为以毫秒为单位设置的持续时间。指定没有新消息的时间,并在该消息后关闭 worker 线程。默认设置为一分钟。

批量取消

要提高性能,您可以将 rsyslog 配置为一次性取消排队多个消息。要为此类 dequeue 设置上限,请使用:

$object(queue.DequeueBatchSize= ”number”)

number 替换为一次可以取消排队的消息的最大数量。请注意,较高的设置结合了更多允许的工作线程数,可增加内存消耗。

终止队列

当终止仍包含信息的队列时,您可以通过为 worker 线程指定完成队列处理的时间间隔来尝试最小化数据丢失:

object(queue.timeoutshutdown=”time”)

以毫秒为单位指定时间。如果在该周期之后仍然有一些 enqueued 消息,worker 会完成当前数据元素,然后终止。因此,未经处理的消息会丢失。可以为 worker 设置另一个时间间隔以完成最终元素:

object(queue.timeoutactioncompletion=”time”)

如果这个超时过期,所有剩余的工作程序都会被关闭。要在关闭时保存数据,请使用:

object(queue.saveonshutdown=”on”)

如果设置,则所有队列元素都会保存到磁盘,然后 rsyslog 终止。

23.4.4. 将 New Syntax 用于 rsyslog 队列

在 rsyslog 7 中提供的新语法中,队列在 action() 对象中定义,可以单独或在 /etc/rsyslog.conf 中的规则集内使用。操作队列的格式如下:

action(type="action_type "queue.size="queue_size" queue.type="queue_type" queue.filename="file_name"

使用要执行该操作的模块的名称替换 action_type,并将 queue_size 替换为队列可以包含的最大消息数。对于 queue_type请选择 disk,或从其中一个内存中队列中选择: 直接链接列表固定阵列。对于 file_name 仅指定文件名,而不是路径。请注意,如果创建新目录以存放日志文件,则必须设置 SELinux 上下文。示例请查看 第 23.4.2 节 “为 rsyslog 日志文件创建新目录”

例 23.13. 定义操作队列

要使用基于异步链接列表的操作队列配置输出操作,可以保存最多 10,000 条信息,请输入以下命令:

action(type="omfile" queue.size="10000" queue.type="linkedlist" queue.filename="logfile")

直接操作队列的 rsyslog 7 语法如下:

. action(type="omfile" file="/var/lib/rsyslog/log_file
   )

带有多个参数的操作队列的 rsyslog 7 语法可以编写如下:

. action(type="omfile"
       queue.filename="log_file"
       queue.type="linkedlist"
       queue.size="10000"
   )

将使用默认工作目录或要设置的最后一个工作目录。如果需要使用不同的工作目录,请在操作队列前添加以下行:

global(workDirectory="/directory")

例 23.14. 使用新语法转发到单一服务器

以下示例基于 转发到单一服务器 过程,以便显示传统 sysntax 和 rsyslog 7 语法之间的区别。The omfwd 插件用于通过 UDPTCP 提供转发。默认值为 UDP。由于插件内置在其中,因此无需加载。

/etc/rsyslog.conf 中使用 以下配置,或在 /etc/rsyslog.d/ 目录中创建包含以下内容的文件:

. action(type="omfwd"
   queue.type="linkedlist"
   queue.filename="example_fwd"
   action.resumeRetryCount="-1"
   queue.saveOnShutdown="on"
   target="example.com" port="6514" protocol="tcp"
   )

其中:

  • queue.type="linkedlist" 启用 LinkedList 内存队列,
  • queue.filename 定义磁盘存储。在上一全局 workDirectory 指令指定的工作目录中,使用 example_fwd 前缀创建备份文件,
  • action.resumeRetryCount -1 设置阻止 rsyslog 在重试连接时丢弃消息(如果服务器没有响应)
  • 如果 rsyslog 关闭,启用 queue.saveOnShutdown="on" 将保存内存中数据,
  • 最后一行将所有收到的消息转发到日志记录服务器,端口规格是可选的。