Verbindungszeitlimit mit Elasticsearch

84
from datetime import datetime
from elasticsearch import Elasticsearch
es = Elasticsearch()

doc = {
    'author': 'kimchy',
    'text': 'Elasticsearch: cool. bonsai cool.',
    'timestamp': datetime(2010, 10, 10, 10, 10, 10)
}
res = es.index(index="test-index", doc_type='tweet', id=1, body=doc)
print(res['created'])

Dieser einfache Code gibt den folgenden Fehler zurück:

elasticsearch.exceptions.ConnectionTimeout: ConnectionTimeout caused by - ReadTimeoutError(HTTPConnectionPool(host='localhost', port=9200): Read timed out. (read timeout=10))

Sehr seltsam, weil der Server bereit und eingestellt ist ( http: // localhost: 9200 / gibt etwas json zurück).

Johann Gomes
quelle

Antworten:

91

Standardmäßig ist das Zeitlimit auf 10 Sekunden eingestellt. Wenn Sie den globalen Zeitlimitwert ändern möchten, können Sie dies erreichen, indem Sie beim Erstellen des Objekts das Flag timeout = your-time setzen .

Wenn Sie das Objekt bereits ohne Angabe des Zeitlimitwerts erstellt haben, können Sie den Zeitlimitwert für eine bestimmte Anforderung mithilfe des Flags request_timeout = your-time in der Abfrage festlegen .

es.search(index="my_index",
          doc_type="document",
          body=get_req_body(),
          request_timeout=30)
Rahul
quelle
Kann dies auf 60 gesetzt werden? Ich bekomme eine Auszeit, auch nachdem ich es 30 eingestellt habe
Kishan Mehta
@ Kishan Wie groß ist dein Körper des Dokuments?
Rohit Patwa
Hallo, @RohitPatwa, mein Problem wurde durch Reduzieren der Länge des Dokuments gelöst. Ich erinnere mich nicht, wie groß der Körper gerade war. Danke für die Hilfe :)
Kishan Mehta
Was ist, wenn mein Chef mich das Zeitlimit nicht ändern lässt und es bei einem einzelnen Datensatz fehlschlägt?
Jonathan Rys
18

Das Problem mit dem Zeitlimit für die Verbindung kann auftreten, wenn Sie den Amazon Elastic Search-Dienst verwenden.

es = Elasticsearch([{'host': 'xxxxxx.us-east-1.es.amazonaws.com', 'port': 443,  'use_ssl': True}])

Der obige Python-Code, bei dem Sie den Standardport von 9200 auf 443 überschreiben und SSL auf true setzen, behebt das Problem.

Wenn kein Port angegeben ist, wird versucht, eine Verbindung zum Port 9200 auf dem angegebenen Host herzustellen, und dies schlägt nach Ablauf der Zeit fehl

Mukund
quelle
Oder Sie können Port 80 es = Elasticsearch verwenden ([{'host': 'xxxxxx.us-east-1.es.amazonaws.com', 'port': 80}])
Olga Akhmetova
6

Dies hat nichts damit zu tun, das Timeout auf 30 Sekunden zu erhöhen. Denken die Leute tatsächlich, dass die elastische Suche bis zu 30 Sekunden dauern sollte, um einen winzigen Treffer zurückzugeben?

Die Art und Weise, wie ich dieses Problem behoben habe, war, unter config / elasticsearch.yml Folgendes zu kommentieren

http.port: 9200
network.host: 'localhost' 

Network.host ist möglicherweise auf 192.168.0.1 eingestellt, was möglicherweise funktioniert. Ich habe es jedoch nur in 'localhost' geändert.

whoopididoo
quelle
17
Wenn der Server zu beschäftigt ist, können Sie diesen Fehler mit einem winzigen Treffer haben.
Devrimbaris 5.
oder wenn es ein Problem mit der DNS-Auflösung gibt, gibt es viele Gründe für eine Zeitüberschreitung
Ethranes
4

Beachten Sie, dass einer der häufigsten Gründe für Zeitüberschreitungen beim Ausführen es.search(oder es.index) eine große Abfragegröße ist. In meinem Fall mit einer ziemlich großen ES-Indexgröße (> 3 Millionen Dokumente) dauerte die Suche nach einer Abfrage mit 30 Wörtern etwa 2 Sekunden, während die Suche nach einer Abfrage mit 400 Wörtern mehr als 18 Sekunden dauerte. Für eine ausreichend große Abfrage werden Sie also nicht einmal Timeout = 30 sparen. Eine einfache Lösung besteht darin, die Abfrage auf die Größe zuzuschneiden, die unterhalb des Zeitlimits beantwortet werden kann.

Wenn Sie das Zeitlimit erhöhen oder erneut versuchen, das Zeitlimit zu überschreiten, können Sie feststellen, ob die Ursache im Verkehr lag. Andernfalls könnte dies Ihr Schuldiger sein.

Vlyubin
quelle
3

elasticsearch.exceptions.ConnectionTimeout: ConnectionTimeout caused by - ReadTimeoutError(HTTPConnectionPool(host='localhost', port=9200): Read timed out. (read timeout=10)) bedeutet, dass die Anforderung nicht in der angegebenen Zeit beendet wurde (standardmäßig Timeout = 10).

Dies funktioniert mit 30 Sekunden:

res = es.index(index="test-index", doc_type='tweet', id=1, body=doc, timeout=30)

Mir Ilias
quelle
2

Versuchen Sie, das Zeitlimit in der Elasticsearch-Initialisierung festzulegen:

es = Elasticsearch([{'host': HOST_ADDRESS, 'port': THE_PORT}], timeout=30)

Sie können sogar einstellen retry_on_timeoutzu Trueund geben Sie die max_retrieseine beliebige Anzahl:

es = Elasticsearch([{'host': HOST_ADDRESS, 'port': THE_PORT}], timeout=30, max_retries=10, retry_on_timeout=True)
Alex Jolig
quelle
1

Mein persönliches Problem wurde gelöst, (timeout = 10000)das praktisch nie erreicht wurde, da die Einträge auf dem Server nur 7.000 waren, aber viel Verkehr herrschte und die Ressourcen überlastet waren. Deshalb wurde die Verbindung unterbrochen

GGEv
quelle
1

Die Gründe für das Zeitlimit können vielfältig sein, und es scheint sinnvoll , die Protokolle auf der Elasticsearch- Seite ( logs/elasticsearch.log) zu überprüfen , um den detaillierten Fehler festzustellen. In unserem Fall war der Fehler bei ES:

primary shard is not active Timeout: [1m]

Wie in diesem Beitrag beschrieben , lag dies daran, dass unsere Festplatte voll war. Wir hatten die Größe (und die Partition) vor einem Tag geändert, um dies zu beheben, aber ES muss neu gestartet werden, wenn das High / Low-Wasserzeichen einmal getroffen wurde (wir sind auf 5.5.x), was wir nicht getan hatten.

Ein einfacher Neustart des ES in der Produktion löste das Problem für uns.

Anupam
quelle
0

Zwei Optionen, die helfen:

1: Erhöhen Sie das Timeout

Das Festlegen einer Zeitüberschreitung hat dieses Problem für mich gelöst. Beachten Sie, dass neuere Versionen eine Einheit benötigen, z timeout="60s".

es.index(index=index_name, doc_type="domains", id=domain.id, body=body, timeout="60s")

Ohne eine Einheit, zum Beispiel durch Einstellung timeout=60, erhalten Sie

elasticsearch.exceptions.RequestError: RequestError(400, 'illegal_argument_exception', 'failed to parse setting [timeout] with value [60] as a time value: unit is missing or unrecognized')

2: Textlänge reduzieren

Es hilft auch, die Textlänge zu reduzieren, z. B. durch Schneiden langer Texte, damit Elastik den Text schneller speichern kann, wodurch auch Zeitüberschreitungen vermieden werden:

es.index(index=index_name, doc_type="domains", id=domain.id, body=text[:5000], timeout="60s")
lorey
quelle
Dies funktioniert nicht, da der Fehler immer noch vorhanden ist und der Timeout-Wert 10 lautet
Alex Jolig