【问题标题】:Tips on making REST client calls faster加快 REST 客户端调用速度的技巧
【发布时间】:2016-02-26 14:02:19
【问题描述】:

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

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

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

这是我一直在试验的方法(credsProviderrequestFactoryrestTemplate 在方法之外被初始化,认为“新”这些重复可能会导致性能问题)

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

【问题讨论】:

  • 你有没有测量过服务器端花费了多少时间?
  • restTemplate.getForObject 平均需要大约 600 毫秒,占我在帖子中提到的 61 秒中的 59 秒
  • URLConnection.getInputStream 平均需要大约 540 毫秒,占我提到的 53 秒中的大部分
  • 似乎这些调用是瓶颈......我可以用什么替换它们或者我怎样才能让它们更有效率我猜是相关的问题......
  • URLConnection::getInputStream() 阻塞,直到服务器端使数据可用。因此,在优化客户端之前,您应该检查在服务器上花费了多少时间以及您的网络往返时间是多少。

标签: java rest resttemplate urlconnection


【解决方案1】:

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

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

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

【讨论】:

  • restTemplate 相关代码也可以这样说。除其他目的外,HttpClient 用于尽可能自动重用打开的连接。根据每个请求构建一个新客户端会破坏任何从这种高级行为中受益的机会。应该将 restTemplate 分配一次它的客户端对象,然后让它从这里工作(整个 Spring 几乎都是关于:“在启动时配置一次,然后让它运行”)。
  • @GPI,当然,只是我对 Spring 模板没有任何实践经验。随意编辑/增强我的答案!
【解决方案2】:

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

看看this的文章。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-02-13
      • 2010-09-26
      • 2014-01-02
      • 2015-05-17
      • 1970-01-01
      • 2010-09-11
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多