CloseableHttpClient执行需要花费很多时间

时间:2015-12-29 11:20:35

标签: java rest

当我调用CloseableHttpClient.exe的方法时,第一次调用它需要花费很多时间。例如,如果我在for bucle中调用API调用10次,则第一次调用所花费的时间比其余调用时间长得多,而且我不知道原因。 如果有人可以帮忙,我将不胜感激。 问候。

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 个答案:

答案 0 :(得分:1)

我没有看到this.httpclient类中ClientHandler是如何初始化的,但通常会在您向远离您的主机执行请求并使用可重用的http连接时发生这种情况(这是为什么第一个请求明显慢于其他请求。) 当您打开与主机的https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/#//apple_ref/c/func/dispatch_get_global_queue连接时,会进行TCP三次握手。这意味着您必须在建立连接之前等待,并且仅在发送实际HTTP请求之后。建立从欧洲到北美某地的连接需要大约90ms甚至更长时间。 TCP
多次使用TCP连接是一种很好的做法。因为在建立TCP连接并完成第一个请求后,您可以发送新请求而无需额外的等待时间。您可以阅读有关Ping time from London to other cities的更多信息
似乎您正在连接到Acano服务器,我不知道他们的数据中心(-s)到底在哪里,因为他们可以在世界各地拥有几个,但该公司位于美国。因此,如果您不是非常接近Arcano的数据中心,那么这似乎是合法的。