java - How to Properly Close Raw RestClient When Using Elastic Search 5.5.0 for Optimal Performance? -


am using spring boot 1.5.4.release microservice connect elasticsearch 5.5.0 instance using low level rest client elasticsearch provides.

pom.xml

<parent>     <groupid>org.springframework.boot</groupid>     <artifactid>spring-boot-starter-parent</artifactid>     <version>1.5.4.release</version> </parent>  <dependencies>     <!-- spring -->     <dependency>         <groupid>org.springframework.boot</groupid>         <artifactid>spring-boot-starter-web</artifactid>     </dependency>      <dependency>         <groupid>org.springframework.boot</groupid>         <artifactid>spring-boot-starter-test</artifactid>         <scope>test</scope>     </dependency>      <!-- elasticsearch -->     <dependency>         <groupid>org.elasticsearch</groupid>         <artifactid>elasticsearch</artifactid>         <version>5.5.0</version>     </dependency>      <dependency>         <groupid>org.elasticsearch.client</groupid>         <artifactid>transport</artifactid>         <version>5.5.0</version>     </dependency>      <!-- apache commons -->     <dependency>         <groupid>org.apache.commons</groupid>         <artifactid>commons-lang3</artifactid>         <version>3.6</version>     </dependency>      <!-- jackson -->     <dependency>         <groupid>com.fasterxml.jackson.core</groupid>         <artifactid>jackson-core</artifactid>         <version>2.8.9</version>     </dependency>      <dependency>         <groupid>com.fasterxml.jackson.core</groupid>         <artifactid>jackson-databind</artifactid>         <version>2.8.9</version>     </dependency>      <dependency>         <groupid>com.fasterxml.jackson.core</groupid>         <artifactid>jackson-annotations</artifactid>         <version>2.8.9</version>     </dependency>      <!-- log4j -->     <dependency>         <groupid>log4j</groupid>         <artifactid>log4j</artifactid>         <version>1.2.17</version>     </dependency>      <!-- junit -->     <dependency>         <groupid>junit</groupid>         <artifactid>junit</artifactid>         <version>4.11</version>         <scope>test</scope>     </dependency>      <!-- swagger -->     <dependency>         <groupid>io.springfox</groupid>         <artifactid>springfox-swagger2</artifactid>         <version>2.6.1</version>         <scope>compile</scope>     </dependency>      <dependency>         <groupid>io.springfox</groupid>         <artifactid>springfox-swagger-ui</artifactid>         <version>2.6.1</version>         <scope>compile</scope>     </dependency> </dependencies> 

everything setup correctly after bunch of hits, client apps reporting http 500 error , appeared in log files:

java.io.ioexception: many open files         @ sun.nio.ch.ioutil.makepipe(native method) ~[na:1.8.0_141]         @ sun.nio.ch.epollselectorimpl.<init>(epollselectorimpl.java:65) ~[na:1.8.0_141]         @ sun.nio.ch.epollselectorprovider.openselector(epollselectorprovider.java:36) ~[na:1.8.0_141]         @ java.nio.channels.selector.open(selector.java:227) ~[na:1.8.0_141]         @ org.apache.http.impl.nio.reactor.abstractmultiworkerioreactor.<init>(abstractmultiworkerioreactor.java:142) ~[httpcore-nio-4.4.5.jar!/:4.4.5]         @ org.apache.http.impl.nio.reactor.defaultconnectingioreactor.<init>(defaultconnectingioreactor.java:79) ~[httpcore-nio-4.4.5.jar!/:4.4.5]         @ org.apache.http.impl.nio.client.ioreactorutils.create(ioreactorutils.java:43) ~[httpasyncclient-4.1.3.jar!/:4.1.3]         @ org.apache.http.impl.nio.client.httpasyncclientbuilder.build(httpasyncclientbuilder.java:666) ~[httpasyncclient-4.1.3.jar!/:4.1.3]         @ org.elasticsearch.client.restclientbuilder.createhttpclient(restclientbuilder.java:202) ~[rest-5.5.0.jar!/:5.5.0]         @ org.elasticsearch.client.restclientbuilder.build(restclientbuilder.java:180) ~[rest-5.5.0.jar!/:5.5.0]         @ com.myapp.controller.searchcontroller.getsearchqueryresults(searchcontroller.java:94) ~[classes!/:1.0] 

inside searchcontroller (the second line after // comment line 94):

@restcontroller @requestmapping("/api/v1") public class searchcontroller {      @requestmapping(value = "/search", method = requestmethod.get, produces="application/json" )     public responseentity<object> getsearchqueryresults(@requestparam(value = "criteria") string criteria) throws ioexception {          // setup http headers         httpheaders headers = new httpheaders();         headers.add("content-type", "application/json");          // setup restclient         restclient restclient = restclient.builder(new httphost("localhost", 9200))         .setrequestconfigcallback(new restclientbuilder.requestconfigcallback() {             @override             public requestconfig.builder customizerequestconfig(requestconfig.builder requestconfigbuilder) {                 return requestconfigbuilder.setconnecttimeout(5000).setsockettimeout(60000);             }         }).setmaxretrytimeoutmillis(60000).build();          // setup query , send , return responseentity...      } } 

its obvious never closed after calling restclient.performrequest() method...

so, put code:

response response = null; try {    // submit query , obtain response    response = restclient.performrequest("post", endpoint,  collections.singletonmap("pretty", "true"), entity); } catch (ioexception e) {    log.error("\n\n\texception: " + e + "\n\n");    e.printstacktrace(); } {    restclient.close(); } 

read on elastic search's documentation restclient class thread-safe...

also, read restclient.performrequestasync() method inexperienced threads , description inside documentation vague.

question(s):

  1. is solution best way handle , close bunch of socket resources?

  2. would appreciate if show me better way use low level restclient elastic search in sense won't cause same issue socket resources not being freed resulting in http 500. should using restclient.performrequestasync? please provide example?

thank taking time read this...

it's not practice create restclient on every single request. should create single instance via configuration bean 1 below:

@configuration public class elasticsearchconfig {      @value("${elasticsearch.host}")     private string host;      @value("${elasticsearch.port}")     private int port;      @bean     public restclient restclient() {         return restclient.builder(new httphost(host, port))         .setrequestconfigcallback(new restclientbuilder.requestconfigcallback() {             @override             public requestconfig.builder customizerequestconfig(requestconfig.builder requestconfigbuilder) {                 return requestconfigbuilder.setconnecttimeout(5000).setsockettimeout(60000);             }         }).setmaxretrytimeoutmillis(60000).build();     } } 

and in searchcontroller class can inject (and add cleanup method close restclient instance when container goes down):

@restcontroller @requestmapping("/api/v1") public class searchcontroller {      @autowired     private restclient restclient;      @requestmapping(value = "/search", method = requestmethod.get, produces="application/json" )     public responseentity<object> getsearchqueryresults(@requestparam(value = "criteria") string criteria) throws ioexception {          // setup http headers         httpheaders headers = new httpheaders();         headers.add("content-type", "application/json");          // setup query , send , return responseentity...          response response = this.restclient.performrequest(...);      }      @predestroy     public void cleanup() {         try {             logger.info("closing es rest client");             this.restclient.close();         } catch (ioexception ioe) {             logger.error("problem occurred when closing es rest client", ioe);         }     }  }     

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -