Chr*_*man 4 .net lucene amazon-ec2 elasticsearch nest
我遇到使用.NET NEST客户端和ElasticSearch的批量索引性能会随着时间的推移而降级,并且会有一定数量的索引和文档数量.
我们ElasticSearch Version: 0.19.11, JVM: 23.5-b02使用Ubuntu Server 12.04.1 LTS 64位和Sun Java 7在m1.large Amazon实例上运行.除了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
Run Code Online (Sandbox Code Playgroud)
ES_MAX_MEM设置为4g,ES_MIN_MEM设置为2g
每天晚上我们在.NET应用程序中使用NEST索引/重新索引~15000个文档.在任何给定时间,只有一个索引<= 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) :
Run Code Online (Sandbox Code Playgroud)
builk索引实现看起来像这样
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();
}
}
Run Code Online (Sandbox Code Playgroud)
重新启动elasticsearch守护进程似乎没有任何区别,但是删除索引并重新编制索引.但几天后我们会遇到同样的慢速索引问题.
我刚刚删除了索引并在每次批量索引操作后重新启用刷新间隔后添加了一个Optimize,希望这可能会使索引降级.
...
...
finally
{
EnableRefreshInterval();
elasticClient.Optimize("products");
}
Run Code Online (Sandbox Code Playgroud)
我在这里做了一些可怕的错事吗?
对不起 - 刚开始写另一篇很长的评论,并认为我只是把它全部放在一个答案中以防其他人受益...
ES_HEAP_SIZE
我在这里注意到的第一件事是你说你将elasticsearch的max和min堆值设置为不同的值.这些应该是一样的.在configuration/init.d脚本中,应该有一个可以设置的EX_HEAP_SIZE.请务必仅设置此值(而不是最小值和最大值),因为它会将最小值和最大值设置为您想要的相同值.如果你不这样做,当你开始需要更多内存时,JVM将阻止java进程 - 最近看到这篇关于github中断的好文章(这里是引用):
设置ES_HEAP_SIZE环境变量,以便JVM对最小和最大内存使用相同的值.将JVM配置为具有不同的最小值和最大值意味着每次JVM需要额外的内存(最多)时,它将阻止Java进程分配它.结合旧的Java版本,这解释了我们的节点在向公共搜索打开时引入更高负载和连续内存分配时所显示的暂停.elasticsearch团队建议设置50%的系统RAM.
还可以查看这篇伟大的文章,了解更多来自战壕的弹性搜索配置.
锁定内存以停止交换
根据我的研究,我发现你还应该锁定java进程可用的内存量,以避免内存交换.我不是这个领域的专家,但我被告知的是,这也将扼杀性能.您可以在elasticsearch.yml配置文件中找到bootstrap.mlockall.
升级
Elasticsearch仍然很新.计划升级相当频繁,因为您所使用的版本(0.19.11)和当前版本(0.20.4)之间引入的错误修复非常重要.有关详细信息,请参阅ES站点.你使用的是Java 7,这绝对是正确的方法,我从Java 6开始,很快意识到它不够好,特别是对于批量插入.
插件
最后,对于遇到类似问题的任何其他人,请安装一个体面的插件来概述您的节点和JVM.我推荐bigdesk - 运行bigdesk然后使用一些批量插入命中弹性搜索,并注意奇怪的堆内存模式,非常多的线程等,它就在那里!
希望有人觉得这很有用!
干杯,詹姆斯
| 归档时间: |
|
| 查看次数: |
6381 次 |
| 最近记录: |