ES查询报错ContentTooLongException排查过程

1、报错堆栈

Caused by: org.apache.http.ContentTooLongException: entity content is too long [186516227] for the configured buffer limit [104857600]
        at org.elasticsearch.client.HeapBufferedAsyncResponseConsumer.onEntityEnclosed(HeapBufferedAsyncResponseConsumer.java:76) ~[elasticsearch-rest-client-7.7.1.jar!/:7.7.1]
        at org.apache.http.nio.protocol.AbstractAsyncResponseConsumer.responseReceived(AbstractAsyncResponseConsumer.java:137) ~[httpcore-nio-4.4.13.jar!/:4.4.13]

2、从报错内容来看,es客户端收到了响应,但是响应的Content-length超过了100M的限制达到了177M导致抛出异常,详见org.elasticsearch.client.HeapBufferedAsyncResponseConsumer#onEntityEnclosed

    @Override
    protected void onEntityEnclosed(HttpEntity entity, ContentType contentType) throws IOException {
        long len = entity.getContentLength();
        if (len > bufferLimitBytes) {
            throw new ContentTooLongException("entity content is too long [" + len +
                    "] for the configured buffer limit [" + bufferLimitBytes + "]");
        }
        if (len < 0) {
            len = 4096;
        }
        this.buf = new SimpleInputBuffer((int) len, getByteBufferAllocator());
        this.response.setEntity(new ContentBufferEntity(entity, this.buf));
    }

3、这个es查询只是一个简单的统计TOP10的一个业务,但是返回的内容为什么会这么大,直接用命令调es接口发现响应也是很小的

4、因为问题只在生产环境有,arthas又看不出来什么特别的,只能直接用tcpdump抓包看调http的请求响应报文到底是什么样子的,请求报文如下,直接使用请求报文中的请求体调es也确实返回了大量的数据。到这里问题其实比较清晰了,经过对比我手动请求es的命令里面没有带size,而程序请求es的报文里面带了size,导致将文档内容在hits中响应了回来,导致响应超大

POST /index/_search HTTP/1.1
Content-Length: 642
Content-Type: application/json
Connection: Keep-Alive

{
    "aggregations": {
        "field": {
            "terms": {
                "field": "field",
                "min_doc_count": 1,
                "order": [
                    {
                        "_count": "desc"
                    },
                    {
                        "_key": "asc"
                    }
                ],
                "size": 10
            }
        }
    },
    "from": 0,
    "query": {
        "bool": {
        }
    },
    "size": 10000,
    "version": true
}

5、接下来看代码里面为什么会带上size为10000,这里可能是我的使用的方式不正确,带上size的地方是在org.springframework.data.elasticsearch.core.RequestFactory#prepareSearchRequest中

6、不纠结根本的改,就是查询的时候显式指定一下size为0,但是因为在org.springframework.data.domain.AbstractPageRequest#AbstractPageRequest中有限制size必须大于0,所以size指定成1可以临时解决这个问题。(因为这里使用es的方式不是直接使用spring原生方式,而是自己包装了一层,根本原因可能还是自己的包装的实现里面有一些不合适的地方,用search去做searchAggregationsCount,search内就会走上兜底size为10000的逻辑,当然直接使用开源的spring方式集成可能也会有类似的问题)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值