将AWS Kinesis Firehose回填到Elasticsearch Service失败的记录

时间:2018-04-13 17:45:19

标签: elasticsearch amazon-kinesis-firehose

我们有一个firehose将记录发送到Elasticsearch Service集群。我们的集群已经填满,一些记录未通过S3。 https://docs.aws.amazon.com/firehose/latest/dev/basic-deliver.html#retry处的文档表明失败的记录可用于回填:"跳过的文档将传递到elasticsearch_failed /文件夹中的S3存储桶,您可以将其用于手动回填"但我还没有找到任何关于如何实现这一目标的文件。

查看记录,它们似乎是包含JSON blob的文本文件的gzip文件,其中包含" rawData"包含我们发送给firehose的原始记录的base64编码字符串的字段。

是否有现有工具可以处理这些来自S3的gzip文件,将其分解并重新提交记录?文档暗示您可以手动回填"它是一个非常标准化的流程,所以我的假设是有人之前做过这个,但我还没有找到方法。

2 个答案:

答案 0 :(得分:1)

遇到相同的问题,修改了上面的脚本以将失败的文档(使用403)回填到现有的Elasticsearch实例

import boto3
import json
import base64
import logger
import requests

s3_client = boto3.client('s3', region_name="xx-xx-x", aws_access_key_id="xxxx", aws_secret_access_key="xxxx")
s3keys = s3_client.list_objects(Bucket="bucketname", Prefix='path/to/folder/file')
for s3key in s3keys['Contents']:
    print(s3key['Key'])
    file = s3_client.get_object(Bucket="bucketname", Key=s3key['Key'])
    text = file['Body'].read().decode("utf-8")
    failure_cases = list(map(lambda x: json.loads(x), filter(None, text.split('\n'))))
    for case in failure_cases:
        data = base64.b64decode(case['rawData'])
        esid = case['esDocumentId']
        esIndexName = case['esIndexName']
        doc = data.decode('utf-8')
        url = ("https://es-domain-name/%s/_doc/%s" %(esIndexName, esid ))
        headers = {"content-type": "application/json", "Accept-Charset": "UTF-8"}
        if case['errorCode'] == '403':
            try:
                print(case['errorCode'])
                r = requests.post(url, data=doc, headers=headers, auth=('user', 'password'))
                response = r.json()
                print(response)
            except:
                pass

答案 1 :(得分:0)

我想手动回填意味着使用一个AWS开发工具包将文档再次发送到Elasticsearch中。 python中的一个示例(使用boto3),该示例从S3读取故障文件并将其中的文档发送到Elasticsearch:

es_client = boto3.client('es', region_name=REGION, aws_access_key_id=ACCESS_KEY_ID, aws_secret_access_key=SECRET_ACCESS_KEY)
s3_client = boto3.client('s3', region_name=REGION, aws_access_key_id=ACCESS_KEY_ID, aws_secret_access_key=SECRET_ACCESS_KEY)

file = s3_client.get_object(Bucket=bucket, Key=key)
text = file['Body'].read().decode("utf-8")
failure_cases = list(map(lambda x: json.loads(x), filter(None, text.split('\n'))))

for case in failure_cases:
    try:
        data = base64.b64decode(case['rawData'])
        es_instance.create(index=case['esIndexName'], id=case['esDocumentId'], body=data)
        logger.debug("Successfully sent {}".format(case['esDocumentId']))
    except RequestError:
        logger.info("Retry failed for Document ID {}\nReason: {}"
                    .format(case['esDocumentId'], case['errorMessage']))