压缩非常奇妙,可以将数据压缩比原始大小更小。我们知道WinRaR,7Zip等压缩工具。Elasticsearch也提供压缩数据功能,可实现对在客户端和服务端节点之间传输数据的压缩。压缩对于处理大数据传输时可减少网络延迟,本文主要内容包括:启用HTTP/TCP压缩,处理Elasticsearch不同版本的压缩的响应信息。
启用HTTP/TCP压缩
ES使得修改HTTP压缩非常容易,仅仅在 elasticsearch.yml文件中提供下面属性即可:
http.compression: true
http.compression_level: 1
TCP压缩使用下面属性:
transport.compress: true
处理Elasticsearch不同版本的压缩的响应信息
前节启用了压缩,下面讨论如何处理压缩响应信息。对于TCP压缩无需任何处理,Elasticsearch使用tcp协议在不同节点之间通信能够正确解压。但启用http压缩,客户端(终端、postman、java client)需要知道如何解压缩,否则会收到无法阅读数据。下面主要聚焦java client情况。
2020.06.18 Elasticsearch7.8版本发布,其中Java库处理压缩非常容易。可以参考文档:Elasticsearch 7.8 release notes
虽然你启用了数据压缩,只有客户端请求压缩时Elasticsearch才压缩数据。java 客户端通过Http request发送额外请求选项要求压缩。请看示例:
RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
.addHeader("Accept-Encoding", "gzip")
.addHeader("Content-type", "application/json");
Elasticsearch 7.7 及以下版本处理压缩响应
ES的java库提供两种客户端,高级Rest客户端和低级Rest客户端。高级不支持处理压缩数据,当接收到压缩响应会直接跑车运行时异常。低级客户端提供Elasticsearch原始响应,因此可以进行解压。有多种方式实现解压,这里仅设计两种:
RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
.addHeader("Accept-Encoding", "gzip")
.addHeader("Content-type", "application/json");
Request request = new Request("GET", "test/_search");
request.setOptions(requestOptions);
Response response = client.getLowLevelClient().performRequest(request);
byte[] entity = EntityUtils.toByteArray(response.getEntity())
String decompressedResponse = "";
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(entity);
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8));) {
decompressedResponse = bufferedReader.lines()
.collect(Collectors.joining());
}
System.out.println(decompressedResponse)
也可以通过下面代码进行解压:
RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
.addHeader("Accept-Encoding", "gzip")
.addHeader("Content-type", "application/json");
Request request = new Request("GET", "test/_search");
request.setOptions(requestOptions);
Response response = client.getLowLevelClient().performRequest(request);
String decompressedResponse = EntityUtils.toString(new GzipDecompressingEntity(response.getEntity()))
System.out.println(decompressedResponse)
Elasticsearch 7.8处理压缩响应
rest高级客户端自动解压数据。上面示例可重写为:
RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
.addHeader("Accept-Encoding", "gzip")
.addHeader("Content-type", "application/json");
SearchRequest request = new SearchRequest("twitter");
SearchResponse searchResponse = client.search(searchRequest, requestOptions);
System.out.println(decompressedResponse)
作为开发者无需写额外逻辑处理响应。如果使用低级Rest客户端仍然需要自己解压缩逻辑,与上面示例一致。
Elasticsearch Release 7.9 及未来 8.0版本
随着新版功能升级,低级Rest客户端也提供了内置解压功能,可以查看pull/55413。这将大大提升java库的开发者应用体验。示例代码如下:
RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder()
.addHeader("Accept-Encoding", "gzip")
.addHeader("Content-type", "application/json");
Request request = new Request("GET", "test/_search");
request.setOptions(requestOptions);
Response response = client.getLowLevelClient().performRequest(request);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println(responseBody);
低级Rest客户端的变化开发者需要留意。如果你已经在代码中增加了解压逻辑会抛出异常,因为尝试解压未压缩的数据。高级客户端没有变化,仍默认提供的解压功能。
总结
本文介绍了Elasticsearch响应数据压缩与解压缩功能,并给出不同版本的实现差异及示例代码。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/115077333