使 REST 客户端调用更快的技巧

Tips on making REST client calls faster

我一直在尝试使用 Spring 的 RestTemplate 和 Java 的 URLConnection 对外部 API 进行 REST 客户端调用.我很沮丧,循环 100 次执行相同的 REST GET 调用(returns 一个小的 JSON 响应)需要大约 60 秒 RestTemplate 和大约 53 秒 URLConnection .我正在测试这个,因为我的网络应用程序需要通过 HTTP GET、PUT 和 POST 对这个外部 API 进行相当多的调用,所以我试图编写这些调用以尽可能高效.

我可以做些什么来提高下面任一代码片段的效率吗?或者是否有另一个库作为 REST 客户端被认为是高效的?我想使用 RestTemplate,但如果这意味着更快的客户端 REST 调用,我也可以通过 URLConnection 进入更低级别。

也许这是我的一个错误假设,但我认为对端点进行 100 次 HTTP GET 调用,returns 一个小的 JSON 响应不会超过 10 秒。

以下是我一直在试验的方法(credsProviderrequestFactoryrestTemplate 是在方法之外初始化的,认为 "new'ing" 这些重复可能会导致性能问题)

public static String performGetRestRequest(String host, int port, String user, String pass, String endPoint) throws Exception {
    credsProvider.setCredentials(
            new AuthScope(host, port),
            new UsernamePasswordCredentials(user, pass));
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider)
            .build();
    requestFactory.setHttpClient(httpclient);

    return restTemplate.getForObject("http://" + host + ":" + port + endPoint, String.class);
}

public static String performGetRestRequestWithPureJava(String host, int port, String endPoint) throws Exception {
    URLConnection connection = new URL("http://" + host + ":" + port + endPoint).openConnection();
    connection.setRequestProperty("Accept-Charset", CHARSET);
    connection.setRequestProperty("Accept", "application/json");

    String inputLine;
    StringBuilder sb = new StringBuilder();

    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), CHARSET));
    while ((inputLine = in.readLine()) != null) {
        sb.append(inputLine);
    }
    in.close();

    return sb.toString();
}

使用 ASyncTask 和 URLConnection 显然比使用现有的其他库要慢。考虑使用 Volley 或 Retrofit。

看看 this 文章。

在开始优化客户端之前,您应该确保时间确实花在了那里。首先,您需要测量服务器响应请求所花费的时间。您的网络往返时间是多少?这将使您更全面地了解时间的去向。

我无法评论 Spring 的 REST 模板,因为我从未使用过它。但是从 URLConnection::getInputStream() 返回的流中读取将阻塞,直到服务器端实际发送数据。因此,对 performGetRestRequestWithPureJava(..) 调用的测量 "client time" 包括网络往返以及服务器响应请求所花费的时间。

附注:如果您向同一目的地发出重复请求,请不要重复创建新的 URLConnection 实例并调用 openConnection()。而是在连接已打开的情况下重新使用单个实例。

使用下面的库。它更快更容易使用

<dependency>
  <groupId>org.asynchttpclient</groupId>
  <artifactId>async-http-client</artifactId>
</dependency>.