2017-06-21 3 views
0

Wir verwenden den elasticsearch REST Java Client (wir sind auf Java 7, können also nicht den normalen elasticsearch Java Client verwenden) um mit unseren elasticsearch Servern zu interagieren. Das funktioniert alles gut, außer wenn wir versuchen, eine anfängliche Indizierung von etwa 1,3 Millionen Dokumenten durchzuführen. Dies läuft für eine Weile, aber nach ein paar hunderttausend Dokumente werden wir vonOutOfMemoryError mit elasticsearch REST Java Client über Apache http nl

java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED 
    at org.apache.http.util.Asserts.check(Asserts.java:46) 
    at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase.ensureRunning(CloseableHttpAsyncClientBase.java:90) 
    at org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(InternalHttpAsyncClient.java:123) 
    at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:343) 
    at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:325) 
    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:218) 
    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:191) 

gefolgt

20/06 21:27:33,153 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) Exception in thread "pool-837116-thread-1" java.lang.OutOfMemoryError: unable to create new native thread 
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.start0(Native Method) 
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.start(Thread.java:693) 
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:334) 
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:194) 
20/06 21:27:33,154 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64) 
20/06 21:27:33,155 ERROR [cid=51][stderr][write:71] (pool-837116-thread-1) at java.lang.Thread.run(Thread.java:724) 

bekommen Wie Sie die Elasticsearch REST-Client verwendet Apache HTTP nio sehen können. Was ich seltsam fand ist, dass die Niobibliothek einen Thread für jede einzelne Anfrage (oder Verbindung?) Erstellt. Aus dem obigen Protokoll können Sie den Thread sehen (pool-837116-thread-1). Es gibt auch viele I/O-Dispatcher-Threads mit steigenden Nummern.

Die Gesamtzahl der Live-Threads scheint sich nicht viel zu ändern. So scheint es eher als Wiederverwendung von Threads ein (oder zwei tatsächlich) neue Thread wird für jeden Verbindungszyklus erstellt. Der Upload ist im Grunde: 1. Erstellen Client

restClient = RestClient.builder(new HttpHost(host.getHost(),host.getPort(),host.getProtocol())/*,new HttpHost(host.getHost(),host.getPort()+1,host.getProtocol())*/) 
          .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { 
           @Override 
           public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { 
            return httpClientBuilder 
              .setDefaultCredentialsProvider(credsProvider) 
                       } 
          }).setMaxRetryTimeoutMillis(30000).build(); 
  1. Anfrage senden mit json Körper und in der Nähe Client

    try { HttpEntity entity = neue NStringEntity (json , ContentType.APPLICATION_JSON); Antwort indexResponse = restClient.performRequest ("PUT", Endpunkt, Parameter, Entität, Header); log.debug ("Antwort # 0 # 1", indexResponse, indexResponse.getStatusLine()); log.debug ("Entität # 0", indexResponse.getEntity());

    }finally{ 
         if(restClient!=null){ 
          log.debug("Closing restClient #0", restClient); 
          restClient.close(); 
         } 
        } 
    

Ist das normal? Warum verwendet Apache keine Threads? Ist das ein Problem mit dem REST-Client elasticsearch, Apache nio oder meinem Code? Ich rufe den RestClient an, nicht sicher, was ich sonst noch machen soll.

Ich habe versucht, die Fadenzahl nur 1 auf dem IO-Reaktor zu setzen:

restClient = RestClient.builder(new HttpHost(host.getHost(),host.getPort(),host.getProtocol())/*,new HttpHost(host.getHost(),host.getPort()+1,host.getProtocol())*/) 
          .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { 
           @Override 
           public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { 
            return httpClientBuilder 
              .setDefaultCredentialsProvider(credsProvider) 
              .setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build()); //set to one thread 
           } 
          }).setMaxRetryTimeoutMillis(30000).build(); 

aber, dass in Bezug auf die Wiederverwendung von Threads nichts ändern.

+0

Verwenden Sie einen Masseneinsatz oder einen Einzeleinsatz? – jvwilge

+0

Ich habe den Grund für den OutOfMemoryError gefunden. Obwohl ich einen try-finally-Block benutzte, in dem ich den Client schließen würde, wurde eine Ausnahme außerhalb dieses Blocks geworfen (der Block umfasste nicht alles D'oh). Aber es sieht immer noch falsch aus, dass so viele Threads erstellt werden (obwohl die Anzahl der gesamten Threads nicht signifikant zunimmt). – Ben

+0

Dies ist eine Eins-zu-eins-Einfügung, da ich sicher sein muss, dass die Daten für jeden hochgeladen wurden. Es verwendet den gleichen Mechanismus wie für die normale Indizierung. – Ben

Antwort

0

Ich habe den Grund für den OutOfMemoryError gefunden. Obwohl ich einen try-finally-Block benutzte, in dem ich den Client schließen würde, wurde eine Ausnahme außerhalb dieses Blocks geworfen (der Block umfasste nicht alles D'oh). Aber es sieht immer noch falsch aus, dass so viele Threads erstellt werden (obwohl die Anzahl der gesamten Threads nicht signifikant zunimmt).

Verwandte Themen