Logstash/elasticsearch 停止接受新数据

Logstash/elasticsearch 停止接受新数据

我已经建立了一个新的概念验证 logstash 系统

CentOS 6.6 (on Vmware 5.5) - single CPU VM with 12G RAM allocated

通过 RPM 安装 Elasticsearch 和 Logstash……

# rpm -q elasticsearch logstash
elasticsearch-1.7.1-1.noarch
logstash-1.5.3-1.noarch

JVM: 1.8.0_51

我输入的数据是以下形式的简单记录……

M1234 z123 2015-01-31 23:28:09.417 8.55373

(字段包括机器名称、用户 ID、日期、时间、登录时间 - 所有内容都是简单的 US-ASCII)

下面是 Logstash 配置(这些数据来自 MSSQL 数据库,目前我正在将其导出到文本文件并将文件传输到 logstash 服务器)。

这对于一天的日志(11K 条记录)来说很有效,但是当我尝试处理今年的积压日志时,它就“挂起了”。

症状包括

  • elasticsearch 仍然响应迅速 - 搜索和配置访问仍然正常
  • 索引中的文档数量停止增加
  • 系统变得必不可少的空闲 - 只有后台磁盘活动和最低限度的 CPU 使用率
  • 如果我尝试停止 logstash 进程(仍在运行),它只会终止kill -9

这似乎发生在 200K 左右的文档中。它不受索引数量的影响 - 我从每日索引开始,然后改为每周索引 - 它仍然在 200K 左右的文档中停止。

因为这是在单台机器上运行的概念证明,所以我将副本数减少到 0,并将分片数减少到 1 - 我认为这对这个问题不会产生任何影响。

尽管我提高了 Logstash 和 Elasticsearch 日志的详细程度,但我没有在 Logstash 和 Elasticsearch 日志中看到任何错误。

我不认为系统耗尽了内存、磁盘空间和文件描述符。

我不确定还要看什么。这感觉像是一个微不足道的问题(对于 ELK 而言),而且我没有在处理我们邮件日志的现有 ELK 设置中看到这个问题(尽管它运行的是早期版本并且有多个 elasticsearch 存储节点)

尽管我确信输入文件中没有奇数字节序列,但我已charset => "US-ASCII"file输入插件节中明确将输入声明为 US_ASCII。我不认为这会带来任何影响(测试仍在进行中)。

更新:虽然导入停滞时日志中没有什么有趣的内容,但是logstash要求关闭时记录的行很有趣……

{:timestamp=>"2015-08-03T10:17:39.104000+0100", :message=>["INFLIGHT_EVENTS_REPORT", "2015-08-03T10:17:39+01:00", {"input_to_filter"=>20, "filter_to_output"=>0, "outputs"=>[]}], :level=>:warn}

对我来说,问题出在过滤阶段,而不是输出到elasticsearch。我已经确认,首先删除elasticsearch输出,只保留stdout。这显示了相同的行为 - 导入在一段时间后停滞。

elasticsearch输出放回去但清除filter部分中的所有内容使我成功完成了数据导入。

我现在已经解决了这个问题 - 详情请见答案。

input {
        file {
                path => "/var/lib/clusters/*"
                type => "clusterF"
                start_position => "beginning"
        }
}

filter {
        mutate {
                remove_field => [ "path", "host" ]
        }
        # 13COMP014   nabcteam    2015-07-29 11:09:21.353 153.493
        if [type] == "clusterF" {
                grok {
                        match => { "message" => "%{NOTSPACE:client} +%{WORD:userid} +%{TIMESTAMP_ISO8601:datestamp} +%{BASE10NUM:elapsed:float}" }
                }
        }
        if [elapsed] < 0 {
                drop {}
        }
        if [elapsed] > 1000.0 {
                drop {}
        }
        if [userid] =~ "[a-z][0-9]{7}" {
                mutate {
                        add_field => [ "userClass", "student" ]
                }
        } else if [userid] =~ "n[a-z].*" {
                mutate {
                        add_field => [ "userClass", "staff" ]
                }
        } else {
                mutate {
                        add_field => [ "userClass", "other" ]
                }
        }
        date {
                match => [ "datestamp", "ISO8601" ]
        }
        mutate {
                remove_field => [ "message" ]
        }
}

output {
        elasticsearch {
                bind_host => "clog01.ncl.ac.uk"
                protocol => "http"
                cluster => "elasticsearch"
                flush_size => 10
                index => "clusters-%{+xxxx.ww}"
        }
}

答案1

一旦我知道摊位就在附近,filter就更output容易找到了。

elasticsearch输出放回去但清除filter部分中的所有内容使我成功完成了数据导入。

我编写了一个简单的perl脚本来根据规范验证输入行grok- 这表明一些用户 ID 包含连字符(这是我没有想到的)。在原始配置中替换+%{WORD:userid}+%{NOTSPACE:userid}给了我一个有效的设置。我怀疑我首先应该做的是在成功时添加一个字段,grok并且仅在该字段存在时才应用其他过滤规则。

我从中得到的主要教训是,简化这类问题很重要,否则寻找潜在原因的空间就会太大。

相关内容