elasticsearch bulk-Indizierung wird langsamer über die Zeit mit konstanter Anzahl von Indizes und Dokumenten
Erlebe ich, dass bulk-Indizierung Leistung mit Hilfe der .NETTO NEST client und ElasticSearch degradiert im Laufe der Zeit mit einer Konstanten Menge von Indizes und Anzahl der Dokumente.
Laufen wir ElasticSearch Version: 0.19.11, JVM: 23.5-b02
auf einen m1.große Amazon-Instanz mit Ubuntu Server 12.04.1 LTS 64 bit und Sun-Java-7. Es gibt nichts anderes läuft diese Instanz außer dem, was kommt, zusammen mit Ubuntu installieren.
Amazon M1 Large Instance: von 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 ist eingestellt auf 4g und ES_MIN_MEM eingestellt ist 2g
Jeden Abend/index reindex ~15000 Dokumente mit NEST in unserem .NET-Anwendung. Zu jedem gegebenen Zeitpunkt gibt es nur einen index mit <= 15000 Dokumente.
wenn der server zuerst installiert wurde, die Indizierung und die Suche war schnell für die ersten paar Tage, dann wird die Indizierung gestartet langsamer und langsamer. die bulk-Indizierung Indizes 100 Dokumente zu einer Zeit, und nach einer Weile würde es dauern, bis zu 15s für eine bulk-operation zu beenden. danach haben wir begonnen, um zu sehen, eine Menge von der folgenden Ausnahme-und die Indizierung von Schleifen zum Stillstand.
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) :
Den builk Indizierung-Implementierung sieht wie folgt aus
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();
}
}
Neustart des elasticsearch-daemon scheint nicht zu keinen Unterschied machen, überhaupt, aber das löschen der index-und re-Indizierung alles tut. Aber nach ein paar Tagen hätten wir die gleichen slow-Indizierung problem.
Ich gerade gelöscht, die index und zusätzlich eine Optimierung nach der re-Aktivierung des refresh-Intervall nach jeder bulk-index-operation in der Hoffnung, dass diese halten könnte, der index von der Verschlechterung.
...
...
finally
{
EnableRefreshInterval();
elasticClient.Optimize("products");
}
Mache ich etwas schrecklich falsch hier?
- 15000 sollten breeze sowohl für NEST und Elasticsearch, was ist die tatsächliche Anzahl der Dokumente und index-Größe nach ein paar Tagen?
- Wie haben Sie auf, da diese Frage mit der ES-Konfiguration? Ich bemerkte eine Sache, dass hier definitiv Bedürfnissen ansprechen; Sie haben max und min ES-heap-Speicher, um andere Werte. Sie sollte gleich sein, irgendwo zwischen 50 und 60% der gesamte Speicher dem system zur Verfügung. Ich habe derzeit bulk-index-batchs von 100.000 Dokumente in jeder minute ein backfill-app mit NEST als der client, so dass 15,000 sollte trivial sein. Du bist auch auf einem sehr alten version von ES - es ist schon einige große Verbesserungen seit 19.11 (derzeit 0.20.4)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sorry - einfach nur angefangen zu schreiben, eine Recht lange Kommentar und dachte, ich würde nur kleben Sie es alle in eine Antwort, falls es profitiert jemand anderes...
ES_HEAP_SIZE
Das erste, was mir aufgefallen ist, dass Sie hier gesagt, Sie setzen die max-und min-heap-Werte für elasticsearch auf unterschiedliche Werte. Diese sollten gleich sein. In der Konfiguration /init.d script sollte es eine EX_HEAP_SIZE, die Sie festlegen können. Achten Sie darauf, nur setzen Sie diese (und nicht die min-und max-Werte), als es die min-und max-Werte auf den gleichen Wert, die ist, was Sie wollen. Wenn Sie dies nicht tun die JVM blockieren von java-Prozessen verwenden, wenn Sie beginnen, benötigen mehr Speicher - finden Sie diesen tollen Artikel eines Ausfalls bei github vor kurzem (hier ein Zitat):
Schauen Sie sich auch diesen tollen Beitrag weitere elasticsearch config aus dem Schützengraben.
Speicher sperren zu Stoppen Tauschen
Aus meiner Forschung habe ich gefunden, dass sollte man auch sperren Sie die Menge an Arbeitsspeicher für den java-Prozess zu vermeiden, Speicher austauschen. Ich bin kein Experte in diesem Bereich, aber habe ich was gesagt worden ist, dass das töten auch Leistung. Finden Sie bootstrap.mlockall in Ihrem elasticsearch.yml config-Datei.
Upgrades
Elasticsearch ist noch Recht neu. Ein upgrade ist relativ Häufig, wie die bug-fixes, die eingeführt wurden, zwischen der version, die Sie waren, 0.19.11) und die aktuelle version (0.20.4) sind sehr wichtig. Finden Sie die ES Website für details. Du bist auf Java 7, das ist definitiv der richtige Weg zu gehen, begann ich auf Java 6 und merkte schnell, dass es war einfach nicht gut genug, vor allem für bulk einfügen.
Plugins
Schließlich jemand anderes, der Erfahrungen ähnliche Probleme, eine anständige plugin installiert für Sie eine übersicht Ihrer Knoten und der JVM. Ich empfehle bigdesk - run bigdesk und dann drücken Sie elasticsearch mit einigen bulk-inserts und watch out für die seltsamen heap-Speicher-Muster, eine sehr große Anzahl von threads, etc, es ist alles da!
Hoffe jemand findet das nützlich!
Cheers,
James
bootstrap.mlockall = true
Sie sollten auch anulimit -l unlimited
in der daemon .sh-Skript, das startet elasticsearch. (Dabei entfernt eine künstliche Grenze auf elasticsearch die Fähigkeit, virtuellen Speicher, notwendig, um die Aktivierung des mlock-Optimierung.) Einstellung ulimits können sehr fummelig, so dass ich auch einulimit -a
Zeile im dump die Werte in das Protokoll. Wenn Sie es richtig gemacht haben, läufttop
zeigen elasticsearch mit etwa den gleichen VIRT-und RSS-Größe sofort auf starten; wenn der RSS ist klein, der mlockall-Einstellung nicht wirksam.Nur Vermutungen:
Als index-Leistung beeinträchtigt, merkst du den index nimmt mehr Platz auf der Festplatte?
Könnte es sein, dass, eher als das ersetzen der alten index oder alte Dokumente, wenn reindexing, sondern Sie werden das hinzufügen einer Reihe von neuen Dokumenten, effektiv verdoppelt die Anzahl der Dokumente, die es wohl mit weitgehend dupliziert Daten. Könnte sich lohnen, packte ein Alter, langsam index und laden Sie Sie in einige Zuschauer um zu Debuggen (Lukas, zum Beispiel). Wenn Sie sehen viel mehr Dokumente als von Ihnen erwartet, dann könnten Sie schauen, dass Sie Ihre neu erstellen erstellen Sie einen neuen index um die alten zu ersetzen, statt.
Seit dem Neustart des daemon das problem nicht beheben lässt, würde ich annehmen öffnen Sie Datei-handles, die Laufenden Prozesse, verbindungen, etc. ausgeschlossen werden kann, obwohl, ich würde wollen, schauen Sie diese Statistiken, und bestimmen, wenn ich sehe, jedem verdächtigen Verhalten auf dem server.
Auch, in Bezug zu Optimieren, sehen Sie möglicherweise einige performance-Verbesserungen mit, sicher, aber es ist eine sehr teure operation ist. Ich würde empfehlen, nur eine Optimierung nach der vollständigen Neuerstellung abgeschlossen ist, anstatt nach jedem inkrementellen bulk-index-operation.
Optimize
in der bulk-Indizierung. Bisher haben wir gesehen, keine Indexierung-Abbau, hoffentlich wird es halten, aber ich habe das Gefühl, unruhig, nicht in der Lage zu lokalisieren des Problems. Ich werde in Lukas und Graben Sie sich durch die Protokolle, wenn die situation erneut Auftritt.