Подтвердить что ты не робот

Как эффективно использовать 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 class 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? Любые мысли?

UPDATE: -

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;
    }
}
4b9b3361

Ответ 1

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

Там мы определили, что 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 для создания своих соединений.

Ответ 2

У меня есть мой многопоточный безопасный одноэлементный шаблон REST, подобный этому в spring:

<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

Ответ 3

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