配置文件

  1. http.compression: true
  2. http.compression_level: 1

TCP压缩使用下面属性:

  1. transport.compress: true

es不同版本的压缩的响应信息

前节启用了压缩,下面讨论如何处理压缩响应信息。对于TCP压缩无需任何处理,Elasticsearch使用tcp协议在不同节点之间通信能够正确解压。但启用http压缩,客户端(终端、postman、java client)需要知道如何解压缩,否则会收到无法阅读数据。下面主要聚焦java client情况。

2020.06.18 Elasticsearch7.8版本发布,其中Java库处理压缩非常容易。可以参考文档:Elasticsearch 7.8 release notes

虽然你启用了数据压缩,只有客户端请求压缩时Elasticsearch才压缩数据。java 客户端通过Http request发送额外请求选项要求压缩。请看示例:

  1. RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
  2. .addHeader("Accept-Encoding", "gzip")
  3. .addHeader("Content-type", "application/json");

es 7.7 及以下版本处理压缩响应

ES的java库提供两种客户端,高级Rest客户端和低级Rest客户端。高级不支持处理压缩数据,当接收到压缩响应会直接跑车运行时异常。低级客户端提供Elasticsearch原始响应,因此可以进行解压。有多种方式实现解压,这里仅设计两种:

  1. RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
  2. .addHeader("Accept-Encoding", "gzip")
  3. .addHeader("Content-type", "application/json");
  4. Request request = new Request("GET", "test/_search");
  5. request.setOptions(requestOptions);
  6. Response response = client.getLowLevelClient().performRequest(request);
  7. byte[] entity = EntityUtils.toByteArray(response.getEntity())
  8. String decompressedResponse = "";
  9. try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(entity);
  10. GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
  11. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8));) {
  12. decompressedResponse = bufferedReader.lines()
  13. .collect(Collectors.joining());
  14. }
  15. System.out.println(decompressedResponse)

也可以通过下面代码进行解压:

  1. RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
  2. .addHeader("Accept-Encoding", "gzip")
  3. .addHeader("Content-type", "application/json");
  4. Request request = new Request("GET", "test/_search");
  5. request.setOptions(requestOptions);
  6. Response response = client.getLowLevelClient().performRequest(request);
  7. String decompressedResponse = EntityUtils.toString(new GzipDecompressingEntity(response.getEntity()))
  8. System.out.println(decompressedResponse)

es 7.8处理压缩响应

rest高级客户端自动解压数据。上面示例可重写为:

  1. RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
  2. .addHeader("Accept-Encoding", "gzip")
  3. .addHeader("Content-type", "application/json");
  4. SearchRequest request = new SearchRequest("twitter");
  5. SearchResponse searchResponse = client.search(searchRequest, requestOptions);
  6. System.out.println(decompressedResponse)

作为开发者无需写额外逻辑处理响应。如果使用低级Rest客户端仍然需要自己解压缩逻辑,与上面示例一致。

es 7.9 及未来 8.0版本

随着新版功能升级,低级Rest客户端也提供了内置解压功能,可以查看pull/55413。这将大大提升java库的开发者应用体验。示例代码如下:

  1. RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
  2. .addHeader("Accept-Encoding", "gzip")
  3. .addHeader("Content-type", "application/json");
  4. Request request = new Request("GET", "test/_search");
  5. request.setOptions(requestOptions);
  6. Response response = client.getLowLevelClient().performRequest(request);
  7. String responseBody = EntityUtils.toString(response.getEntity());
  8. System.out.println(responseBody);

低级Rest客户端的变化开发者需要留意。如果你已经在代码中增加了解压逻辑会抛出异常,因为尝试解压未压缩的数据。高级客户端没有变化,仍默认提供的解压功能。