几次成功后,Elasticsearch查询突然失败

After several successes, Elasticsearch queries suddenly fail

我编写了一个 Perl 脚本,简而言之,它将从 Elasticsearch 数据库中提取数据并以特定格式打印出来。

如果有任何特定的代码片段有助于解决我的问题,请告诉我,我将非常乐意在此处 post。我不会剪切和粘贴整个脚本,因为它差不多有 1000 行长,而且是我公司的 属性.

当前使用的模块: strict, warnings, LWP::UserAgent, CGI, POSIX, JSON, Modern::Perl, Term::ANSIColor, & Scalar::Util

声明等:

# Declare user agent object
my $ua = LWP::UserAgent->new;

# Set custom HTTP request header fields
my $req = HTTP::Request->new( POST => $serverEndpoint );
$req->header( 'content-type' => 'application/json' );

my $post_data = '{ 
        "fields" : [' . $arrayList . '],
        "sort" : [
            { "@timestamp" : { "order" : "asc" } }
        ],
        "query" : {
            "filtered" : {
                "filter" : {
                    "range" : {
                        "@timestamp" : {
                            "gte" : "' . $lowerBound . '",
                            "lte" : "' . $upperBound . '"
                        }
                    }
                }
            }
        }
    }';

$arrayList 之前被定义为一串字段,并用引号括起来(例如 "field1"、"field2"、"field3")。

# Receives results from ES (this is Perl syntax for querying ES)
    $req->content( $post_data );
    $resp = $ua->request( $req );
    $myResults = $resp->content();
    #say $myResults; die;

    # Changes string (as returned by http request) to JSON format that is compatible with Perl
    $decoded = JSON::XS::decode_json( $myResults );

    @data = @{ $decoded->{ "hits" }{ "hits" } };
    @tempResponse = @data;
    my $lengthOfArray = scalar @tempResponse;

至此,@data 已经有了我需要的信息。我已经检查过了,看起来不错。我保存了当前响应的长度以备将来使用。

$scrollID = $decoded->{ "_scroll_id" };

我为下一部分保存卷轴 ID。

现在我有了初始数据集,我反复查询数据库,直到(好吧,至少,应该如此)数据库被完全查询。

如果 $lengthOfArray < 0,我可以知道数据库何时被完全查询。如果这是真的,那么就没有更多的数据可以获取了。

while ( $lengthOfArray > 0 ) {
        $ua = LWP::UserAgent->new;

        $serverEndpoint = "http://localhost:9200/_search/scroll?scroll=1m&scroll_id=" . $scrollID;
        $req = HTTP::Request->new( POST => $serverEndpoint );
        $req->header( 'content-type' => 'application/json' );

        $req->content( $post_data );

        #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                 
        $resp = $ua->request( $req );
        #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        $myResults = $resp->content();

        # Changes string (as returned by http request) to JSON format that is compatible with Perl
        $decoded = JSON::XS::decode_json( $myResults );

        @tempResponse = @{ $decoded->{ "hits" }{ "hits" } };
        #print "@tempResponse\n";

        @data = ( @data, @tempResponse );

        $lengthOfArray = scalar @tempResponse;
    }

我正在处理的数据集非常庞大。一切都非常顺利(我已经测试过了。如果我只让它 运行 循环 600 次,它就没问题)直到它达到循环计数 #801。 在循环的第 801 次,它挂断了。它在那里停留了大约一分钟,然后死于错误消息:

malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "read timeout at /usr...")

我已将错误追踪到上面所有 !!!!!s 周围的行。循环在第 801 次循环时挂在该行上。

没有真正的迹象表明为什么会发生此错误。同样,如果我通过循环 800 次而不是 801 次,它会起作用。

我知道所有数据都在 Elasticsearch 中。我应该从中获得大约 12,000 个哈希值。我可以通过@data[0]、@data[1] 等访问前 800 个哈希值,但在那之后我就不走运了。

如有任何帮助,我们将不胜感激。我今天花了整整 9 个小时的工作时间来尝试解决这个问题,但没有成功。真的,如果你甚至可以要求澄清我解释的某些部分,这可能足以找到答案。

所以,如果有任何事情我可以做些什么来清理我输入的内容(显示 ES URL 给出的内容),请告诉我。

非常非常感谢!

======================================== ==================

编辑 #1: 我找到了问题的根源。没有意义,但就是这样。

在 $post_data 我有 $arrayList。它包含我之前从字段数组中获取的 36 个字段的列表。它的格式如下:

"field1","field2","field3","field4"

我注意到,如果我删除其中一个字段,无论是哪个字段,请求都会顺利通过。

哪个字段都无所谓

======================================== ==================

编辑 #2: 这可能会有用。如果我让请求超时,它会给出以下错误消息:

malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "read timeout at /usr..." at *scriptName.pl* line 403, <STDIN> line 5.

403行如下:

$decoded = JSON::XS::decode_json( $myResults );

就在

的正下方
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                 
$resp = $ua->request( $req );
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

======================================== ==================

编辑 #3: 我尝试打印出 $resp->content() 以查看在挂断之前是否有任何东西看起来很奇怪。它最初并不......内容看起来就像它应该的那样。

不过,过了一会儿,它放弃并打印出以下消息:

{"error":"SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; shardFailures{SearchContextMissingException[No search context found for id [2378]]}{SearchContextMissingException[No search context found for id [2379]]}{SearchContextMissingException[No search context found for id [2380]]}","status:404"}

这完全覆盖了屏幕,直到我打断它。

======================================== ==================

最终编辑:有效!

声明部分确实不需要更改任何内容。我 did 更改了查询的大小,以便减少查询(我认为 ES 的 RAM 已满)。所以现在这就是 $post_data 的样子:

my $post_data = '{
        "size": 1000,
        "fields" : [' . $arrayList . '],
        "sort" : [
            { "@timestamp" : { "order" : "asc" } }
        ],
        "query" : {
            "filtered" : {
                "filter" : {
                    "range" : {
                        "@timestamp" : {
                            "gte" : "' . $lowerBound . '",
                            "lte" : "' . $upperBound . '"
                        }
                    }
                }
            }
        }
    }';

请注意顶部附近的尺寸发生了怎样的变化。我不认为这是解决我的问题的原因,但无论如何它应该有助于提高性能。

我认为我遇到的问题是 while 循环。最初循环被设计为继续 运行 直到 hits 数组为空,但由于某种原因它甚至在那之后继续进行。不知道为什么,也许我稍后会弄清楚。

我所做的是检查是否定义了我期望在 hits 数组中找到的成员之一。如果未定义,则循环失败。

还有其他一些小的变化,但那才是真正的大变化。现在效果很好! ...仅仅2天后。

感谢 Stack Overflow!

每个滚动请求都应该使用最新的 scroll id 即 scroll_id 在上一个滚动响应中返回。

从代码摘录来看,您似乎正在使用第一个响应中的滚动 ID,可能将其更改为使用最新的 scroll_id 应该会有所帮助

即在 while 块中你需要 $scrollID = $decoded->{ "_scroll_id" };

while ( $lengthOfArray > 0 ) {
        $ua = LWP::UserAgent->new;

        $serverEndpoint = "http://localhost:9200/_search/scroll?scroll=1m&scroll_id=" . $scrollID;
        $req = HTTP::Request->new( POST => $serverEndpoint );
        $req->header( 'content-type' => 'application/json' );

        $req->content( $post_data );

        #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                 
        $resp = $ua->request( $req );
        #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        $myResults = $resp->content();

        # Changes string (as returned by http request) to JSON format that is compatible with Perl
        $decoded = JSON::XS::decode_json( $myResults );
        $scrollID =  $decoded->{ "_scroll_id" };
        @tempResponse = @{ $decoded->{ "hits" }{ "hits" } };
        #print "@tempResponse\n";

        @data = ( @data, @tempResponse );

        $lengthOfArray = scalar @tempResponse;
    }

可能这应该有所帮助。