java处理ES查询突破10000条的限制方案

1.为什么要限制10000条

 默认情况下,Elasticsearch集群中每个分片的搜索结果数量限制为10000。这是为了避免潜在的性能问题。

2.突破10000条限制的办法

  1. 使用scroll API:scroll API可以帮助我们在不加载所有数据的情况下获取所有结果。它会在后台执行查询以获取滚动ID,并将其用于进行后续查询。这样就可以一次性获取所有结果,而不必担心限制
  2. 修改ES默认设置,将10000修改成10万或者50万,这样的话要考虑ES内存溢出的问题,不推荐

3.具体方法

  1. 使用scroll API
public ConcurrentLinkedDeque<FramePickingInfoVo> getSearchRequest(FramePickingPageVo vo){
        long start = System.currentTimeMillis();
        ConcurrentLinkedDeque<FramePickingInfoVo> list=new ConcurrentLinkedDeque<>();
        try{
            //构建查询请求
            SearchRequest baseSubOrderIndexRequest = CloudBaseQueryBuilder.getBaseSubOrderIndexRequest();
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQuery = CloudBaseQueryBuilder.getBaseFramePickBoolQuery(vo,true);
            //设置size(10000)
            sourceBuilder.size(batchSize);
            sourceBuilder.query(boolQuery);
            //设置排序方式
            getSort(vo.getOrderByType(),sourceBuilder);
            // 滚动查询请求
            SearchRequest searchRequest = new SearchRequest(BASE_SUB_ORDER_DIMENSION_INDEX);
            searchRequest.source(sourceBuilder);
            //设置请求滚动时间窗口时间
            searchRequest.scroll(TimeValue.timeValueMinutes(scrollTime));

            //执行首次检索
            SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);

            //首次检索返回scrollId,用于下一次的滚动查询
            String scrollId = searchResponse.getScrollId();
            //获取首次检索命中结果

            SearchHit[] searchHits = searchResponse.getHits().getHits();
            ConcurrentLinkedDeque<FramePickingInfoVo> framPickDateInfos = getFramPickDateInfos(searchResponse);
            list.addAll(framPickDateInfos);
            // 处理滚动结果
            while (searchHits != null && searchHits.length > 0) {
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
                scrollRequest.scroll(TimeValue.timeValueMinutes(scrollTime));

                searchResponse = elasticsearchClient.scroll(scrollRequest, RequestOptions.DEFAULT);
                scrollId = searchResponse.getScrollId();
                searchHits = searchResponse.getHits().getHits();
                ConcurrentLinkedDeque<FramePickingInfoVo> framPickDateInfos1 = getFramPickDateInfos(searchResponse);
                list.addAll(framPickDateInfos1);
            }

            // 清理滚动上下文
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);

            ClearScrollResponse clearScrollResponse = elasticsearchClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            boolean succeeded = clearScrollResponse.isSucceeded();

            long end = System.currentTimeMillis();
            System.out.println("共执行时间:" + (end - start) / 1000 + " s");

        } catch (Exception e) {
            System.out.println("===error==" + e.getMessage());
            e.printStackTrace();
        }
        return list;
    }
  1. 修改ES默认配置
# 调大查询窗口巨细,比方100w
PUT index/_settings
{
  "index.max_result_window": "1000000"
}
# 检查查询最大数
GET index/_settings
---
{
  "demo_scroll" : {
    "settings" : {
      "index" : {
        "number_of_shards" : "5",
        "provided_name" : "demo_scroll",
        "max_result_window" : "1000000",
        "creation_date" : "1680832840425",
        "number_of_replicas" : "1",
        "uuid" : "OLV5W_D9R-WBUaZ_QbGeWA",
        "version" : {
          "created" : "6082399"
        }
      }
    }
  }
}
### 配置 Elasticsearch 实现白名单访问 为了实现 Elasticsearch 的白名单访问控制,可以通过多种方式完成这一目标。以下是常见的方法及其具体配置: #### 方法一:通过防火墙设置 IP 白名单 如果服务器运行在云环境中(如 AWS、Azure 或 GCP),可以直接利用其内置的安全组功能来限制Elasticsearch 端口的访问。例如,在 AWS 中创建一个安全组规则,仅允许特定 IP 地址访问端口 9200。 对于本地环境,则可以在操作系统层面使用 `iptables` 来定义白名单规则。以下是一个简单的 Linux 示例[^1]: ```bash sudo iptables -A INPUT -p tcp --dport 9200 -s 192.168.1.100 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 9200 -j DROP ``` 上述命令表示只接受来自 `192.168.1.100` 的连接请求,并拒绝其他所有来源的请求。 #### 方法二:借助 X-Pack 安全特性 Elastic Stack 提供了强大的安全性插件——X-Pack Security,它支持细粒度的身份验证和授权机制。启用此功能后,管理员能够指定哪些客户端被授予访问权限。 要激活这些保护措施,请编辑 `elasticsearch.yml` 文件并加入如下参数[^2]: ```yaml xpack.security.enabled: true network.host: 0.0.0.0 transport.host: localhost shield.authc.realms.native.order: 0 shield.transport.ssl.enabled: false shield.http.ssl.enabled: false discovery.zen.minimum_master_nodes: 1 ``` 注意这里启用了身份认证服务 (`xpack.security.enabled`) 并设置了监听地址为全局(`network.host`). 同时还需要设定用户名密码用于登录校验. 另外, 如果想进一步限定可连入系统的IP范围的话, 可以考虑修改下面这个选项: ```yaml http.cors.enabled : true http.cors.allow-origin : "*" ``` 将 `"*"` 替换为你希望开放的具体域名列表或者直接写成单个固定值比如 `"http://example.com"` #### 方法三:Docker Compose 方案中的网络隔离策略 当采用 Docker 运行 Elastic 和 Kibana 应用程序的时候,推荐构建专属的 overlay network ,从而达到物理上的分离效果。这样即使外部恶意攻击者突破了一层防护屏障也无法轻易接触到核心组件。 参照给定的例子[^3], 创建名为 'elastic-net' 自定义网桥模式网络之后再部署关联的服务实例. ```dockerfile version: '2' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2 container_name: es-node1 environment: ES_JAVA_OPTS: "-Xmx512m -Xms512m" discovery.type: single-node ELASTIC_PASSWORD: changeme ports: - "9200:9200" networks: - elastic-net kibana: depends_on: - elasticsearch image: docker.elastic.co/kibana/kibana:7.4.2 container_name: kb-server restart: always environment: SERVER_NAME: kibana.example.org ELASTICSEARCH_URL: http://elasticsearch:9200/ ports: - "5601:5601" networks: - elastic-net networks: elastic-net: driver: bridge ``` 以上脚本片段展示了如何声明两个相互依赖的服务节点并通过同一张虚拟局域网通信交互的过程。其中特别强调的是关于跨主机调用部分,默认情况下会自动解析到内部DNS记录指向的实际位置而非原始输入字符串形式。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值