python urllib2导出elasticsearch数据时 返回 "urllib2.HTTPError: HTTP Error 500: Internal Server Error"

0、业务场景

将ES中某个index的某个字段的所有数据,导出到文件中

1、ES数据导出方法简述

ES数据导出方法,我主要找到了以下几个方面,欢迎大家补充:

  • ES官方API:snapshot and restore module

The snapshot and restore module allows to create snapshots of individual indices or an entire cluster into a remote repository like shared file system, S3, or HDFS. These snapshots are great for backups because they can be restored relatively quickly but they are not archival because they can only be restored to versions of Elasticsearch that can read the index.

   简而言之,是个对ES集群的镜像化以及快速回复的工具。不满足本次需求的针对某个字段输出的要求,所以不再继续看。感兴趣的同学可以查看 Elasticsearch Reference [5.0]ModulesSnapshot And Restore

  • ES的Java API:

   虽说Java大法是我用的最多的编程语言,但是linux上运行Java脚本实在麻烦。抛出一个Java ES导出文件的链接,感兴趣的同学请自便:elasticsearch使用Java API批量数据导入和导出

  • ES的Python API:

   回归正题,Google搜“elasticsearch导出数据”的第一匹配结果,是一个Python脚本写的,链接是:lein-wang/elasticsearch_migrate

#!/usr/bin/python
#coding:utf-8
‘‘‘
    Export and Import ElasticSearch Data.
    Simple Example At __main__
    @author: [email protected]
    @modifier: [email protected]
    @note:  uncheck consistency of data, please do it by self
‘‘‘

import json
import os
import sys
import time
import urllib2

reload(sys)
sys.setdefaultencoding(‘utf-8‘)

class exportEsData():
    size = 10000
    def __init__(self, url,index,type,target_index):
        self.url = url+"/"+index+"/"+type+"/_search"
        self.index = index
        self.type = type
        self.target_index = target_index #替换原有的index
        self.file_name = self.target_index+"_"+self.type+".json"
    def exportData(self):
        print("export data begin...\n")
        begin = time.time()
        try:
            os.remove(self.file_name)
        except:
            os.mknod(self.file_name)
        msg = urllib2.urlopen(self.url).read()
        #print(msg)
        obj = json.loads(msg)
        num = obj["hits"]["total"]
        start = 0
        end =  num/self.size+1 # read size data one bulk
        while(start<end):
            try:
                msg = urllib2.urlopen(self.url+"?from="+str(start*self.size)+"&size="+str(self.size)).read()
                self.writeFile(msg)
                start=start+1
            except urllib2.HTTPError, e:
                print ‘There was an error with the request‘
                print e
                break
        print(start)
        print("export data end!!!\n total consuming time:"+str(time.time()-begin)+"s")
    def writeFile(self,msg):
        obj = json.loads(msg)
        vals = obj["hits"]["hits"]
        try:
            cnt = 0
            f = open(self.file_name,"a")
            for val in vals:
                val_json = val["_source"]["content"]
                f.write(str(val_json)+"\n")
                cnt += 1
        finally:
            print(cnt)
            f.flush()
            f.close()

class importEsData():
    def __init__(self,url,index,type):
        self.url = url
        self.index = index
        self.type = type
        self.file_name = self.index+"_"+self.type+".json"
    def importData(self):
        print("import data begin...\n")
        begin = time.time()
        try:
            s = os.path.getsize(self.file_name)
            f = open(self.file_name,"r")
            data = f.read(s)
            #此处有坑: 注意bulk操作需要的格式(以\n换行)
            self.post(data)
        finally:
            f.close()
        print("import data end!!!\n total consuming time:"+str(time.time()-begin)+"s")
    def post(self,data):
        print data
        print self.url
        req = urllib2.Request(self.url,data)
        r = urllib2.urlopen(req)
        response = r.read()
        print response
        r.close()

if __name__ == ‘__main__‘:
    ‘‘‘
        Export Data
        e.g.
                            URL                    index        type
        exportEsData("http://10.100.142.60:9200","watchdog","mexception").exportData()

        export file name: watchdog_mexception.json
    ‘‘‘
    exportEsData("http://88.88.88.88:9200","mtnews","articles","corpus").exportData()

    ‘‘‘
        Import Data

        *import file name:watchdog_test.json    (important)
                    "_" front part represents the elasticsearch index
                    "_" after part represents the  elasticsearch type
        e.g.
                            URL                    index        type
        mportEsData("http://10.100.142.60:9200","watchdog","test").importData()
    ‘‘‘
    #importEsData("http://10.100.142.60:9200","watchdog","test").importData()
    #importEsData("http://127.0.0.1:9200/_bulk","chat","CHAT").importData()
    #importEsData("http://127.0.0.1:9200/_bulk","chat","TOPIC").importData()

3、遇到的问题

万事俱备,python run代码后,出现了问题:

"urllib2.HTTPError: HTTP Error 500: Internal Server Error"

而且根据程序中的doc count计数信息,发现不论bulk size如何变(尝试了10/50/100/500/1000/5000/10000),总是卡在了第10000篇文档,然后urllib就抛异常。

同事黄大哥分析原因,可能是以下几个方面:

  • 没有平衡bulk的速率,生产多,超过了消费能力,超过了es服务端的TPS (这里黄大哥按照人生经验建议一个bulk在5~15MB最合适)
  • 系统端问题,需查看日志

首先,通过在while循环里面增加sleep语句并减少bulk size,降低ES的TPS,但是仍然在10000篇文档导出的时候出现了 HTTP STATUS 500 的错误,此法不通。

第二种原因,这时候需登录ES宿主机查看log。

发现log中有如下信息,

Caused by: QueryPhaseExecutionException[Result window is too large, from + size must be less than or equal to: [10000] but was [11000]. See the scroll api for a more efficient way to request lar       ge data sets. This limit can be set by changing the [index.max_result_window]index level parameter.]

正如 urllib2中HTTP状态码含义 一文中的

“5XX 回应代码以“5”开头的状态码表示服务器端发现自己出现错误,不能继续执行请求”

确实是服务器端的问题。

4、解决的方法

言归正传,这个问题既然定位了,那么解决方法肯定是有的,参考ES报错Result window is too large问题处理

需要对对应index在配置上,做如下定义:

curl -XPUT http://88.88.88.88:9200/mtnews/_settings -d ‘{ "index" : { "max_result_window" : 10000000}}‘

对log中提示的 index.max_result_window 字段进行修改(默认的为10000)

5、ES学习的经验

  • 发现问题要及时看日志,这样可以节约时间 23333
时间: 2024-10-12 13:35:21

python urllib2导出elasticsearch数据时 返回 "urllib2.HTTPError: HTTP Error 500: Internal Server Error"的相关文章

在使用pydelicious时出现HTTP Error 500: Internal Server Error的错误的解决方法:

问题:在学习<集体智慧编程>的过程中,第二章中如果你遇到了pydelicious.PyDeliciousException: HTTP Error 500: Internal Server Error这样的错误具体的 解决方法我是在stack overflow上找到的,原文链接分为两个部分 http://stackoverflow.com/questions/29543799/pydelicious-get-popularprogramming- doesnt-return-any-valid

SpringMVC3中返回json字符串时500 Internal Server Error的处理方案

搭建 Spring3+MyBatis+Rest+BootStrap+JBPM项目环境后,测试发现了一个操蛋的问题.使用Spring MVC的自动类型转换为JSON时,后台数据List/Map获取完全正常,可是JS获取data报500错误.后台无任何异常信息. 问题解决思路:后台数据操作正常,数据返回前端时候异常,问题集中在Spring的jackson json转换上.而Spring用了第三方的Jackson Json数据转换,异常信息的获取需要靠它,代码中加入如下部分: 1 /** 2 * 查询

spring cloud 调用接口间歇性返回http 500 - Internal Server Error的错误

查找了各种资料都没找到解决办法,token失效,网络问题,接口服务问题,基础服务问题,都考虑过,但是没能解决,偶尔发现服务器网络配置中存在一个virbr0虚拟网卡,问了下了网管,删除这个对服务并没有影响,决定删除这个virbr0, [root@Node1 ~]# ifconfig virbr0 down [root@Node1 ~]# brctl delbr virbr0 之后问题就莫名消失了,有知道原理的朋友欢迎交流 原文地址:https://www.cnblogs.com/yzlsthl/p

zuul网管配置其他服务时 HTTP Status 500 – Internal Server Error

1.这个错误是由三个原因导致的 (1).我在给类的接口命名的时候前面少加了一个/ (2)给zuul配置路由的时候多加了个服务名,serviceId名称就是spring的name,而不是eureka注入服务的那个名称 spring: application: name: worksserver routes: works: #works服务配置 path: /works/** #制定好path和serviceId,所有以path开头的请求都会被路由到对应的服务.如下面/hiapi/**被路由到se

导出EXCEL数据时防止数值变科学计数的办法

网上有很多说法,最简单直接正确的做法是判断一下是否为数值以及长度,然后给单元格加上以下CSS即可: mso-generic-font-family:auto;   mso-font-charset:134;    mso-number-format:"\@";   mso-background-source:auto;   mso-pattern:auto; 这个办法我是从:http://www.cnblogs.com/joinger/articles/1322931.html 这个博

IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效

IIS7.5 HTTP 错误500.19-Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效 -------------------------------------------------------------------------------------------------------------- 设置应用程序池的版本,应用程序池的版本要低于发布程序的版本(同样的程序,在两台服务器上部署时,一台有问题,另外一台正常) -----------

解决PHP导出大量数据时设置超链接的问题

今天在做导出excel功能时,由于要导出的数据很大,所以没有使用PHPExcel,而是使用动态生成文件流的方式来导出,这时遇到一个问题,怎么把某个单元格的值设置为超链接呢. 设置单元格的值的代码如下: 最初的想法是看能不能从PHPExcel中找到相似的代码参考,找了半天没有找到,然后就搜索引擎搜关键字[ Data ss:Type ],发现找到的内容都是跟[ <Data ss:Type="String"> ]有关的,没有我想要的东西,只能再找. 这是,我找到了一篇文章: 这里

mysql插入数据时返回出入数据ID

INSERT INTO user_info (name,gender,height,age)VALUES('sa','女','120','12');SELECT @@IDENTITY @@identity是表示的是最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,是系统定义的全局变量.一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头.比如有个表A,它的自增列是id,当向A表插入一行数据后,如果插入数据后自增列的值自动增加至101,则通过select @@i

使用SQLServer2005插入一条数据时返回当前插入数据的ID

在执行完插入后 再执行 select @@identity from users 就OK 就是刚才插入的那行的 ID了 补充: @@identity 表示当前新增的主键ID 这个是在一个session中查找的, SELECT MAX(id) FROM Users 执行这个查询,就可以返回最新的ID   来自为知笔记(Wiz)