Сжатие - это потрясающе, сделать что-то меньше исходного размера - звучит как волшебство, но это возможно. Мы знаем это из наших WinRar, 7Zip или других инструментов. Даже Elasticsearch имеет свойство сжимать данные, которые будут передаваться между узлами и клиентами, это может быть очень полезно для уменьшения сетевых задержек при обработке огромных ответов от Elasticsearch.
Что такое Elasticsearch?
Elasticsearch - это распределенный поисковый и аналитический механизм с открытым исходным кодом для всех типов данных, включая текстовые, числовые, геопространственные, структурированные и неструктурированные. Elasticsearch построен на базе Apache Lucene и был впервые выпущен в 2010 году компанией Elasticsearch N.V. (сейчас известной как Elastic). Известный своими простыми REST API, распределенным характером, скоростью и масштабируемостью, Elasticsearch является центральным компонентом стека Elastic, набора инструментов с открытым исходным кодом для ввода, обогащения, хранения, анализа и визуализации данных. Обычно называемый ELK Stack (в честь Elasticsearch, Logstash и Kibana), Elastic Stack теперь включает богатую коллекцию легких агентов доставки, известных как Beats, для отправки данных в Elasticsearch.
Включить сжатие/компрессию HTTP/TCP
Elastic очень упростил включение http-компрессии на своих узлах. Достаточно указать следующие свойства в файле elasticsearch.yml:
1 2 | http.compression: true http.compression_level: 1 |
Или следующее свойство для сжатия tcp:
1 | transport.compress: true |
Работа со сжатыми ответами
С помощью изменений, сделанных в предыдущем разделе, мы включили сжатие. При включении сжатия tcp вам не нужно ничего делать для обработки сжатых данных. Elasticsearch будет использовать коммуникационный протокол tcp для связи между различными узлами Elasticsearch и сможет сам распаковать эти данные. Но когда вы включили http-сжатие, ваш клиент (терминал, postman, java-клиент) должен знать, как распаковать данные, иначе вы получите нечитаемые данные. В этой статье мы сосредоточимся на java-клиенте.
18 июня 2020 года компания Elastic выпустила Elasticsearch 7.8 с библиотекой java, которая упрощает работу со сжатыми данными.
Даже если вы разрешили Elasticsearch отправлять вам сжатые данные, Elasticsearch будет сжимать их только тогда, когда клиент запрашивает их. Клиент java может запросить его, отправив дополнительные параметры запроса в http-запросе, см. пример ниже:
1 2 3 | RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder() .addHeader("Accept-Encoding", "gzip") .addHeader("Content-type", "application/json"); |
Обработка сжатых ответов Elasticsearch 7.8
В релизе 7.8 клиент высокого уровня rest получил возможность автоматически распаковывать сжатые данные. Приведенный выше пример можно переписать:
1 2 3 4 5 6 | 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 7.9 и 8.0
В предстоящем выпуске клиент низкого уровня также будет иметь встроенную функцию декомпрессии. Это значительно улучшит работу разработчиков с пользователями Java-библиотеки, так как не потребует никакой пользовательской логики декомпрессии в вашей кодовой базе. Пример кода для низкоуровневого клиента будет следующим:
1 2 3 4 5 6 7 8 | 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) |
Это изменение в низкоуровневом клиенте также повлечет за собой изменения для конечных пользователей. Если у вас уже есть собственная логика декомпрессии, то она, вероятно, вызовет исключение во время выполнения, так как будет пытаться декомпрессировать не сжатые данные (потому что они уже декомпрессированы клиентом). Остальной высокоуровневый клиент остается нетронутым и по-прежнему способен распаковывать сжатые данные из коробки.