2015-12-29 2 views
0

Когда я делаю вызов метода CloseableHttpClient.execute, для завершения первого раза я его вызываю так много времени. Например, если я вызываю вызов API 10 раз в a для bucle, первый вызов занимает гораздо больше времени, чем остальная часть вызова, и я не знаю причины. Буду признателен, если кто-то может помочь. С уважением.Завершение CloseableHttpClient занимает так много времени

public static void main(String[] args) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, Exception 
    { 
     AcanoAPICallsTest2 test = new AcanoAPICallsTest2(); 
     AcanoAPIHandler clientHandler = test.getClientHandler(); 

     if (clientHandler.getConnectCode() == HttpStatus.SC_OK)  { 

      int statusCode = clientHandler.executeMethod(CommonSettings.GET, "/api/xxx); 

      } 
     } 

     clientHandler.shutDownClient(); 
    } 


public class AcanoAPIHandler extends ClientHandler 
{ 
    protected Logger logger = Logger.getLogger(this.getClass()); 
    private final String LOCATION = "Location"; 
    private String location; 
// private int connectCode = HttpStatus.SC_SERVICE_UNAVAILABLE; 

    /** 
    * Returns the "Location" field of the response header (if exists) 
    * 
    * @return 
    */ 
    public String getLocationHeaderResponse() 
    { 
     return location; 
    } 

    // default constructor 
    public AcanoAPIHandler() 
    { 
     super(); 
    } 

    public AcanoAPIHandler(String protocol, String host, Integer port, String username, String password) 
    { 
     super(protocol, host, port, username, password); 
    } 

    @Override 
    public int executeMethod(String type, String path, List<BasicNameValuePair>... nvps) 
    { 
     int statusCode = super.executeMethod(type, path, nvps); 
     this.location = null; 
     if (type.equalsIgnoreCase(CommonSettings.POST) || type.equalsIgnoreCase(CommonSettings.PUT)) 
     { 
      // if statusCode is 200, set the location header 
      if (statusCode == HttpStatus.SC_OK) 
      { 
       Header[] h = this.getResponse().getAllHeaders(); 
       for (int i = 0; i < h.length; i++) 
       { 
        if (h[i].getName().equalsIgnoreCase(LOCATION)) 
        { 
         String locationStr = h[i].getValue(); 
         String[] split = locationStr.split("/"); 
         if (split.length > 0) 
         { 
          this.location = split[split.length - 1]; 
          break; 
         } 
        } 
       } 
      } 
     } 

     return statusCode; 

    } 

} 

ClientHandler.executeMethod

public int executeMethod(String type, String path, List<BasicNameValuePair>... nvps) 
{ 
    int statusCode = -1; 
    HttpUriRequest request = createUriRequest(type, path); 
    this.responseContent = null; 
    this.response = null; 

    try 
    { 
     if (nvps.length > 0) 
     { 
      if (type.equalsIgnoreCase(CommonSettings.POST)) 
      { 
       ((HttpPost) request).setEntity(new UrlEncodedFormEntity(nvps[0], "UTF-8")); 
      } 
      else if (type.equalsIgnoreCase(CommonSettings.PUT)) 
      { 
       ((HttpPut) request).setEntity(new UrlEncodedFormEntity(nvps[0], "UTF-8")); 
      } 
      else 
      { 
       logger.warn("Can only set entity on POST/PUT operation, ignoring nvps"); 
      } 
     } 
    } 
    catch (UnsupportedEncodingException ex) 
    { 
     java.util.logging.Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    if (this.httpclient != null) 
    { 
     try 
     { 
      long start = System.currentTimeMillis(); 

      this.response = this.httpclient.execute(request); 

      long end = System.currentTimeMillis(); 
      long res = end - start; 
      System.out.println("httpclient.execute " + " seconds: "+res/1000); 

      statusCode = response.getStatusLine().getStatusCode(); 
      HttpEntity entity = response.getEntity(); 
      if (entity != null) 
      { 
       InputStream fis = entity.getContent(); 
       this.responseContent = convertStreamToString(fis); 
       EntityUtils.consume(entity); 
       fis.close(); 
      } 
     } 
     catch (IOException ex) 
     { 
      java.util.logging.Logger.getLogger(ClientHandler.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      return SERVER_ERROR; 
     } 
     finally 
     { 
      // release connection 
      if (type.equalsIgnoreCase(CommonSettings.GET)) 
      { 
       ((HttpGet) request).releaseConnection(); 
      } 
      else if (type.equalsIgnoreCase(CommonSettings.POST)) 
      { 
       ((HttpPost) request).releaseConnection(); 
      } 
      else if (type.equalsIgnoreCase(CommonSettings.PUT)) 
      { 
       ((HttpPut) request).releaseConnection(); 
      } 
      else if (type.equalsIgnoreCase(CommonSettings.DELETE)) 
      {     
       ((HttpDelete) request).releaseConnection(); 
      } 

      // close the response 
      try 
      { 
       if (this.response != null) 
       { 
        this.response.close(); 
       } 
      } 
      catch (IOException ex) 
      { 
       java.util.logging.Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex); 
       return SERVER_ERROR; 
      } 
     } 

    } 

    return statusCode; 
} 
+1

Можете ли вы разместить код? –

ответ

1

Я не вижу, как this.httpclient инициализируется в ClientHandler классе, но обычно это происходит, когда вы выполняете запрос к хосту, который находится далеко от вас и использования многоразовые http-соединения (поэтому первый запрос заметно медленнее, чем другие).
Когда вы открываете соединение TCP с хостом, выполняется трехстороннее рукопожатие TCP. Это означает, что вам нужно подождать, пока соединение не будет установлено, и только после отправки фактического HTTP-запроса. Установление связи из Европы куда-нибудь в Северной Америке займет ~ 90 мс и более. Ping time from London to other cities
Использование TCP-соединения несколько раз - хорошая практика. Поскольку после установления TCP-соединения и выполнения первого запроса вы можете отправлять новые запросы без дополнительного времени ожидания. Вы можете узнать больше о HTTP persistent connection
Кажется, что вы подключаетесь к серверам Acano, я точно не знаю, где находится их центр данных (-s), потому что они могут иметь пару из них по всему миру, но компания находится в США. Так что кажется законным, если вы не очень близки к Центру данных Arcano.

+0

Я запускаю свою программу Java на двух разных серверах в одном месте, и результат отличается, на одном из серверов время отклика <1 с, а на другом сервере время ответа составляет 28 секунд. В журнале я вижу, что за звонок занимает так много времени: DEBUG [org.apache.http.conn.HttpClientConnectionManager] Подключение к /xx.202.xxx.11:443 – Guti

+0

1sg означает 1сек? Согласованы ли эти результаты, как вы сделали 10 последовательных попыток (каждый из которых состоит из 10 запросов) на каждом сервере и каждый раз, когда первый запрос на втором сервере был более медленным? Первый запрос в строке медленнее на обоих серверах или только на втором? Выполняют ли другие (и другие) запросы на разных серверах столько же, сколько и первые запросы? – dezhik

+0

Какую версию библиотеки HttpClient вы используете? – dezhik

Смежные вопросы