最近从es拉数据的时候报出来的,查了下,很多blog都写的是调整search.max_open_scroll_context,但是这种并不是最优解决方案,没有从根源处解决问题 。

Scroll 

https://www.elastic.co/guide/en/elasticsearch/reference/1.6/search-request-scroll.html 

首先,什么是scroll,简而言之就是类似分页查询,在查询url中会有这种指定该会话保持多久,这个是保持一分钟,返回值中会有个 _scroll_id,下一次请求会根据这个请求拉取剩余数据,反复如此,直到hits数组为空位置。

_search?scroll=1m
import requests

url = conf.elk_url + self.elk_index + '/_search?size=10000&scroll=1m'
header = {'Content-Type': 'application/json'}
first_results = requests.request('POST', url, headers=header, json=query_json).json()

#................
#................
#................

url = conf.elk_url + '_search/scroll'
header = {'Content-Type': 'application/json'}
data = {
    "scroll": "1m",
    "scroll_id": first_results ['_scroll_id']
}
results = requests.request('POST', url, headers=header, json=data).json()

当我们有多个并行请求,并且请求保持的时间比较长的时候,就有可能报这个错。 

 解决方案

虽然这种修改 search.max_open_scroll_context 的方式也可以解决报错,但是并不是最佳的解决方案( 前提是该次并行请求所创建的scroll_context 没有达到最大值,否则还是应该修改该参数)

import requests

header = {'Content-Type': 'application/json'}                                
url = conf.elk_url + '_cluster/settings'
change_data = {
    "persistent" : {
        "search.max_open_scroll_context": 5000
    },
    "transient": {
        "search.max_open_scroll_context": 5000
    }
}
requests.request('PUT',
                    url,
                    headers=header,
                    json=change_data))

我个人认为最佳的解决方案是在使用完该scroll之后,手动调用清除的api去清除该scroll。

该api可以传入多个scroll_id,就像下面的代码,也可以只传入一个,就像注释掉的代码一样。

import requests

header = {'Content-Type': 'application/json'}                                
del_url = conf.elk_url + '_search/scroll'
delete_data = {
    "scroll_id": [
        results1['_scroll_id'],
        results2['_scroll_id'],           
    ]
}
#delete_data = {
#    "scroll_id": {
#        results['_scroll_id']          
#    }
#}
requests.request('DELETE',
                    del_url,
                    headers=header,
                    json=delete_data))

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐