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):
is solution best way handle , close bunch of socket resources?
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
Post a Comment