Я столкнулся с тем, что производительность массового индексирования с использованием клиента .NET NEST и ElasticSearch со временем ухудшается при постоянном количестве индексов и количестве документов.
Мы запускаем ElasticSearch Version: 0.19.11, JVM: 23.5-b02
на экземпляре Amazon m1.large с 64-разрядной версией Ubuntu Server 12.04.1 LTS и Sun Java 7. На этом экземпляре больше ничего не работает, кроме того, что поставляется вместе с установкой Ubuntu.
Крупный экземпляр Amazon M1: с http://aws.amazon.com/ec2/instance-types/
7.5 GiB memory
4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute Units each)
850 GB instance storage
64-bit platform
I/O Performance: High
EBS-Optimized Available: 500 Mbps
API name: m1.large
Для ES_MAX_MEM установлено значение 4g, а для ES_MIN_MEM установлено значение 2g.
Каждую ночь мы индексируем/переиндексируем ~15000 документов, используя NEST в нашем приложении .NET. В любой момент времени существует только один индекс с ‹= 15000 документов.
когда сервер был впервые установлен, индексация и поиск были быстрыми в течение первых нескольких дней, затем индексация начала становиться все медленнее и медленнее. массовое индексирование индексирует 100 документов за раз, и через некоторое время для завершения массовой операции потребуется до 15 секунд. после этого мы начали видеть множество следующих исключений и остановку индексации.
System.Net.WebException: The request was aborted: The request was canceled.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) :
Реализация встроенной индексации выглядит так
private ElasticClient GetElasticClient()
{
var setting = new ConnectionSettings(ConfigurationManager.AppSettings["elasticSearchHost"], 9200);
setting.SetDefaultIndex("products");
var elastic = new ElasticClient(setting);
return elastic;
}
private void DisableRefreshInterval()
{
var elasticClient = GetElasticClient();
var s = elasticClient.GetIndexSettings("products");
var settings = s != null && s.Settings != null ? s.Settings : new IndexSettings();
settings["refresh_interval"] = "-1";
var result = elasticClient.UpdateSettings(settings);
if (!result.OK)
_logger.Warn("unable to set refresh_interval to -1, {0}", result.ConnectionStatus == null || result.ConnectionStatus.Error == null ? "" : result.ConnectionStatus.Error.ExceptionMessage);
}
private void EnableRefreshInterval()
{
var elasticClient = GetElasticClient();
var s = elasticClient.GetIndexSettings("products");
var settings = s != null && s.Settings != null ? s.Settings : new IndexSettings();
settings["refresh_interval"] = "1s";
var result = elasticClient.UpdateSettings(settings);
if (!result.OK)
_logger.Warn("unable to set refresh_interval to 1s, {0}", result.ConnectionStatus == null || result.ConnectionStatus.Error == null ? "" : result.ConnectionStatus.Error.ExceptionMessage);
}
public void Index(IEnumerable<Product> products)
{
var enumerable = products as Product[] ?? products.ToArray();
var elasticClient = GetElasticClient();
try
{
DisableRefreshInterval();
_logger.Info("Indexing {0} products", enumerable.Count());
var status = elasticClient.IndexMany(enumerable as IEnumerable<Product>, "products");
if (status.Items != null)
_logger.Info("Done, Indexing {0} products, duration: {1}", status.Items.Count(), status.Took);
if (status.ConnectionStatus.Error != null)
{
_logger.Error(status.ConnectionStatus.Error.OriginalException);
}
}
catch(Exception ex)
{
_logger.Error(ex);
}
finally
{
EnableRefreshInterval();
}
}
Перезапуск демона elasticsearch, похоже, не имеет никакого значения, но удаление индекса и повторная индексация всего имеют значение. Но через несколько дней у нас будет та же проблема медленного индексирования.
Я просто удалил индекс и добавил оптимизацию после повторного включения интервала обновления после каждой операции массового индексирования в надежде, что это может предотвратить деградацию индекса.
...
...
finally
{
EnableRefreshInterval();
elasticClient.Optimize("products");
}
Я делаю что-то ужасно неправильно здесь?