如何使用RequestFactory高效地使用RestTemplate?

时间:2015-03-27 07:37:36

标签: java multithreading performance resttemplate

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

我已使用RestTemplateHttpComponentsClientHttpRequestFactory上设置了http请求超时(READ和CONNECTION超时)。

以下是我的界面:

public interface Client {

    // for synchronous
    public String getSyncData(String key, long timeout);

    // for asynchronous
    public String getAsyncData(String key, long timeout);
}

以下是我的客户端界面实现 -

public class DataClient implements Client {

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

    // for synchronous call
    @Override
    public String getSyncData(String key, long timeout) {
        String response = null;

        try {
            Task task = new Task(key, restTemplate, timeout);

            // direct call, implementing sync call as async + waiting is bad idea. 
            // It is meaningless and consumes one thread from the thread pool per a call.               
            response = task.call();
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
        }

        return response;
    }

    // for asynchronous call
    @Override
    public Future<String> getAsyncData(String key, long timeout) {
        Future<String> future = null;

        try {
            Task task = new Task(key, restTemplate, timeout);
            future = executor.submit(task); 
        } catch (Exception ex) {
            PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, key);
        }

        return future;
    }
}

以下是我的简单任务类

class Task implements Callable<String> {

    private RestTemplate restTemplate;
    private String key;
    private long timeout; // in milliseconds

    public Task(String key, RestTemplate restTemplate, long timeout) {
        this.key = key;
        this.restTemplate = restTemplate;
        this.timeout = timeout;
    }

    public String call() throws Exception {

        String url = "some_url_created_by_using_key";

        // does this looks right the way I am setting request factory?
        // or is there any other effficient way to do this?
        restTemplate.setRequestFactory(clientHttpRequestFactory());
        String response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);

        return response;
    }

    private static ClientHttpRequestFactory clientHttpRequestFactory() {
        // is it ok to create a new instance of HttpComponentsClientHttpRequestFactory everytime?
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(timeout); // setting timeout as read timeout
        factory.setConnectTimeout(timeout); // setting timeout as connect timeout
        return factory;
    }   
}

现在我的问题是 - 每次在Task类的调用方法中使用RestTemplatesetRequestFactory的方式是否有效?由于RestTemplate非常重要,所以不确定我是否做对了。

每次都可以创建HttpComponentsClientHttpRequestFactory的新实例吗?它会贵吗?

如果我们需要在其上设置读取和连接超时,那么使用RestTemplate的正确有效方法是什么。

这个库将像这样使用 -

String response = DataClientFactory.getInstance().getSyncData(keyData, 100);

1 个答案:

答案 0 :(得分:2)

据我所知,您重复使用相同的RestTemplate对象,但每个Task正在执行此行:restTemplate.setRequestFactory(clientHttpRequestFactory());。这似乎可能有竞争条件,例如:一个Task可以设置另一个RequestFactory意外使用的Task

否则,您似乎正确使用RestTemplate

您的超时多久更改一次?如果您大多使用一次或两次超时,则可以使用带有预加载超时的RestTemplate构造函数创建一个或两个RequestFactory。如果您是提高效率的人,请在每次请求新的超时时创建一个HashMap<Integer, RestTemplate>缓存RestTemplate特定超时。

否则,查看RestTemplate's constructorHttpComponentsClientHttpRequestFactory's constructor的代码,它们看起来并不特别重,因此重复调用它们可能不会成为瓶颈。