Skip to main content
 首页 » 编程设计

Elasticsearch 响应数据压缩功能详解

2022年07月19日195over140

压缩非常奇妙,可以将数据压缩比原始大小更小。我们知道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
阅读延展