Как эффективно использовать RestTemplate в многопоточной среде?

я работаю над проектом, в котором мне нужно сделать вызов HTTP URL на мой сервер, который работает Restful Service который возвращает ответ в виде JSON-строки.

ниже мой основной код, который использует future и callables -

public class TimeoutThreadExample {

    private ExecutorService executor = Executors.newFixedThreadPool(10);

    public String getData() {
        Future<String> future = executor.submit(new Task());
        String response = null;

        try {
            response = future.get(100, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}

ниже Task класс, который реализует Callable интерфейс и использует RestTemplate...

class Task implements Callable<String> {

    private RestTemplate restTemplate = new RestTemplate();

    public String call() throws Exception {

        String url = "some_url";
        String response = restTemplate.getForObject(url, String.class);

        return response;
    }
}

и теперь у меня ниже код в другом классе DemoTest что называет getData метод TimeoutThreadExample класс 5000 times последовательно

public class DemoTest { 
   public static void main(String[] args) {

        TimeoutThreadExample bc = new TimeoutThreadExample();

        for (int i = 0; i <= 5000; i++) {
        //  TimerTest timer = TimerTest.getInstance(); // line 1
            bc.getData();
        //  timer.getDuration(); // line 2
        }
    }
}       

поэтому мой вопрос должен RestTemplate будьте статичны здесь в моем Task class как будто я вижу это правильно, я воссоздаю весь пул соединений для каждого запроса в RestTemplate который не правильный путь, я думаю..

Примечание: если я делаю RestTemplate статическим, то я вижу лучшую производительность от конца до конца по сравнению с нестатическим RestTemplate после комментирования line1 и line2 в DemoTest класса, который измеряет производительность.

в общем, как правильно использовать RestTemplate в многопоточной среде? В настоящее время я вызываю последовательно getData метод 5000 раз по одному, но некоторые клиенты будут называть его многопоточным способом, поэтому нужно знать, что является лучшим способом иметь RestTemplate в многопоточной среде..

может быть, использовать ConnectionFactory в конструкторе RestTemplate? Любой мысли?

обновление:-

public class TimeoutThreadExample {

    private ExecutorService executor = Executors.newFixedThreadPool(10);
    private RestTemplate restTemplate = new RestTemplate();

    public String getData() {
        Future<String> future = executor.submit(new Task(restTemplate));
        String response = null;

        try {
            response = future.get(100, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}

и ниже TaskClass -

class Task implements Callable<String> {

    private RestTemplate restTemplate;

    public Task(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String call() throws Exception {

        String url = "some_url";
        String response = restTemplate.getForObject(url, String.class);

        return response;
    }
}

3 ответов


поправьте меня, если я не понял ваш вопрос. Он очень похож на предыдущий здесь.

вот, мы определили, что RestTemplate потокобезопасным. Поэтому нет причин не делиться им там, где это имеет смысл, т. е. везде, где вы используете его таким же образом. Ваш пример кажется идеальным местом для этого.

как вы заявили, воссоздание нового экземпляра RestTemplate для каждого Task экземпляр расточительный.

Я бы создал RestTemplate на TimeoutThreadExample и передать его в Task в качестве аргумента конструктора.

class Task implements Callable<String> {

    private RestTemplate restTemplate;

    public Task(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String call() throws Exception {

        String url = "some_url";
        String response = restTemplate.getForObject(url, String.class);

        return response;
    }
}

таким образом Вы разделяете RestTemplate экземпляр между всеми вашими Task объекты.

отметим, что RestTemplate использует SimpleClientHttpRequestFactory для создания своих соединений.


у меня есть мой многопоточный безопасный шаблон Singleton REST, связанный так весной:

<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams" id="httpConnectionManagerParams">
    <property name="connectionTimeout" value="10000"/>
</bean>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager" id="httpConnectionManager">
    <property name="params" ref="httpConnectionManagerParams"/>
</bean>
<bean class="org.apache.commons.httpclient.params.HttpClientParams" id="httpClientParams">
    <property name="authenticationPreemptive" value="true"/>
    <property name="soTimeout" value="10000"/>
</bean>
<bean class="org.apache.commons.httpclient.HttpClient" id="httpClient">
    <constructor-arg ref="httpClientParams"/>
    <constructor-arg ref="httpConnectionManager"/>
</bean>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory" id="httpClientFactory">
    <constructor-arg ref="httpClient"/>
</bean>
<bean class="org.springframework.security.oauth.consumer.client.OAuthRestTemplate" id="restTemplate">
    <constructor-arg ref="httpClientFactory"/>
    <constructor-arg ref="myResource"/>
    <property name="messageConverters">
        <list>
            <ref bean="marshallingHttpMessageConverter"/>
        </list>
    </property>
</bean>

обратите внимание, что я использую OAuthRestTemplate и myResource относится к ресурсу OAuth, который я опустил, поскольку он не имеет отношения. Вместо OAuthRestTemplate вы можете так же легко использовать org.springframework.web.client.RestTemplate http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html


на RestTemplate является потокобезопасным после сборки, Так что вы можете создать один экземпляр и все ваши задачи разделяю. Это будет намного эффективнее, потому что вы исключаете стоимость строительства из каждой задачи и уменьшаете нагрузку на сборщик мусора.