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

时间:2015-07-29 00:48:23

标签: perl elasticsearch bigdata

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

如果任何特定的代码片段有助于解决我的问题,请告诉我,我们非常乐意在此处发布这些代码。我不会剪切和粘贴整个脚本,因为它几乎是1000行长。它是我公司的财产。

目前使用的模块: strict,warnings,LWP :: UserAgent,CGI,POSIX,JSON,Modern :: Perl,Term :: ANSIColor,&标量::的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;

此时,@ dat拥有我需要的信息。我已经检查了它,看起来是正确的。我保存了当前响应的长度以备将来使用。

$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。在801st通过循环的时间,它被挂断了。它在死亡之前会在那里停留一段时间,然后才能显示错误消息:

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

我已经将错误追溯到了上面包含所有!!!!!的行。第801次循环时,循环挂在该行上。

没有关于此错误发生原因的真实指标。同样,如果我经历了800次循环,但不是801次,它会起作用。

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

非常感谢任何帮助。今天我花了整整9个小时的工作日试图弄明白这一点没有运气。真的,如果你甚至可以要求我澄清一些可能足以找到答案的解释。

所以,如果有任何,我可以清理我输入的内容(显示ES网址提供的内容),请告知我们。

非常非常感谢你!

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

编辑#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-&gt; 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"}

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

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

最终编辑:工作正常!

声明部分中确实无需更改任何内容。我做了更改查询的大小,以便减少查询次数(我认为ES的内存已经填满)。所以现在这就是$ post_data的样子:

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

注意顶部附近的尺寸是如何变化的。我不认为这是解决我的问题的方法,但无论如何它应该有助于提高表现。

我相信我遇到的问题是使用while循环。最初循环被设计为继续运行,直到命中数组为空,但由于某种原因,它在此之后仍然继续运行。不知道为什么,也许我以后会想到这一点。

我做的是检查是否定义了我希望在hits数组中找到的其中一个成员。如果没有定义,它就会使循环失败。

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

谢谢Stack Overflow!

1 个答案:

答案 0 :(得分:2)

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

从代码摘录看起来看起来你正在使用第一个响应中的滚动ID,可能会改变它以使用最新的scroll_id应该有帮助

即。在 while 块中,您需要 $ scrollID = $ decoding-&gt; {“_ 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;
    }

可能这应该有所帮助。