Java 如何在多线程环境中高效使用 RestTemplate?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21242812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:35:43  来源:igfitidea点击:

How to use RestTemplate efficiently in Multithreaded environment?

javamultithreadingstaticconnection-poolingresttemplate

提问by AKIWEB

I am working on a project in which I need to make a HTTP URL call to my server which is running Restful Servicewhich returns back the response as a JSON String.

我正在开发一个项目,在该项目中我需要对正在运行的服务器进行 HTTP URL 调用,该服务器Restful Service将响应作为 JSON 字符串返回。

Below is my main code which is using the futureand callables-

下面是我使用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;
    }
}

Below is my Taskclass which implements the Callableinterface and uses the RestTemplate...

下面是我的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;
    }
}

And now I have below code in another class DemoTestwhich calls the getDatamethod in TimeoutThreadExampleclass 5000 timessequentially -

现在我有下面的代码在另一大类DemoTest它调用的getData方法TimeoutThreadExample5000 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
        }
    }
}       

So my question is should RestTemplatebe static here in my Task classas if I see it correctly, I am recreating the whole connection pool for each request in RestTemplatewhich is not the right way I guess..

所以我的问题应该RestTemplate是静态的,Task class就好像我没看错一样,我正在为每个请求重新创建整个连接池,RestTemplate我猜这不是正确的方式。

NOTE:If I am making RestTemplate static, then I see better performance end to end as compared to non static RestTemplateafter commenting out line1 and line2 in DemoTestclass which measures the performance.

注意:如果我将 RestTemplate 设为静态,那么RestTemplate在注释掉DemoTest衡量性能的类中的line1 和 line2 之后,与非静态相比,我看到端到端的性能更好。

In general what is the right way to use RestTemplatein Multithreading environment? Currently I am calling sequentially getDatamethod 5000 times one by one but some customer will call it in a multithreaded way so need to know what is the best way to have RestTemplate in a multithreaded environment..

一般来说,RestTemplate在多线程环境中使用的正确方法是什么?目前我正在getData一个接一个地调用顺序方法 5000 次,但有些客户会以多线程方式调用它,所以需要知道在多线程环境中使用 RestTemplate 的最佳方法是什么..

May be to use ConnectionFactory in the RestTemplate constructor? Any thoughts?

可能是在 RestTemplate 构造函数中使用 ConnectionFactory 吗?有什么想法吗?

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

And below my TaskClass-

在我的下面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;
    }
}

采纳答案by Sotirios Delimanolis

Correct me if I didn't understand your question. It seems very similar to the previous one here.

如果我不明白你的问题,请纠正我。它似乎与这里的前一个非常相似。

There, we determined that RestTemplateis thread-safe. There is therefore no reason not to share it wherever it makes sense to, ie. wherever you are using it in the same way. Your example seems like the perfect place to do so.

在那里,我们确定这RestTemplate是线程安全的。因此,没有理由不在任何有意义的地方共享它,即。无论您在哪里都以相同的方式使用它。您的示例似乎是这样做的理想场所。

As you stated, recreating a new instance of RestTemplatefor each Taskinstance is wasteful.

正如您所说,RestTemplate为每个Task实例重新创建一个新实例是浪费的。

I would create the RestTemplatein TimeoutThreadExampleand pass it to the Taskas a constructor argument.

我会创建RestTemplateinTimeoutThreadExample并将其Task作为构造函数参数传递给 the 。

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

This way you share the RestTemplateinstance between all your Taskobjects.

这样您就可以RestTemplate在所有Task对象之间共享实例。

Note that RestTemplateuses SimpleClientHttpRequestFactoryto create its connections.

请注意,RestTemplate用于SimpleClientHttpRequestFactory创建其连接。

回答by Taylor

I have my multi-thread-safe singleton REST template wired like this in spring:

我的多线程安全单例 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>

Please note I'm using an OAuthRestTemplate, and myResourcerefers to the oauth resource stuff which I've omitted as it's not relevant. Instead of an OAuthRestTemplateyou could just as easily use a org.springframework.web.client.RestTemplatehttp://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

请注意,我使用的是OAuthRestTemplate, 并myResource指的是我省略的 oauth 资源内容,因为它不相关。而不是OAuthRestTemplate你可以很容易地使用org.springframework.web.client.RestTemplatehttp://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

回答by Raedwald

A RestTemplateis thread safe once constructed, so you can construct one instance and have all your tasks share it. That will be much more efficient, because you eliminate the construction cost from each task, and reduce the load on the garbage collector.

ARestTemplate一经构建就是线程安全的,因此您可以构建一个实例并让您的所有任务共享它。这会更有效率,因为您消除了每个任务的构建成本,并减少了垃圾收集器的负载。