I'm trying to access web API via java.
The API is on https server.
Unfortunately it works very slow.
When I access the API via my web browser, it gives the response in 1 second.
When I access the API via java, it gives the response in 3 seconds.
What am I doing wrong? How can I get the response faster?
I noticed that the slow part is this line: HttpResponse response1 = httpclient.execute(httpGet);
Here's my code:
static DefaultHttpClient httpclient ;
static {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("LOGIN", "PASSWORD");
httpclient = new DefaultHttpClient();
HttpHost targetHost = new HttpHost("SERVER.org", 443, "https");
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(targetHost.getHostName(), targetHost.getPort()),
creds);
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local
// auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
readXml("https://SERVER.org/PATH");
}
public static String readXml(String urlToRead){
try {
HttpGet httpGet = new HttpGet(urlToRead);
HttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
BufferedReader in;
String inputLine;
String result="";
try {
in = new BufferedReader(new InputStreamReader(entity1.getContent(),"UTF-8"));
while ((inputLine = in.readLine()) != null) {
result+=inputLine+"\n";
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return result;
} finally {
httpGet.releaseConnection();
}
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return null; }
I think it is slow in HTTPS handshake. There is no reason for new DefaultHttpClient in each request. You should use PoolingClientConnectionManager to handle multi-http-client.
public Client(int maxConnectPerHost, int maxConnection, int connectTimeOut, int socketTimeOut,
String cookiePolicy, boolean isAutoRetry, boolean redirect) {
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, new TrustManager[] {
new TrustAnyTrustManager()
}, new java.security.SecureRandom());
} catch (Exception e) {
// throw something
}
// if a ssl certification is not correct, it will not throw any exceptions.
Scheme https = new Scheme("https", 443, new SSLSocketFactory(sslcontext,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER));
Scheme http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());
SchemeRegistry sr = new SchemeRegistry();
sr.register(https);
sr.register(http);
connectionManager = new PoolingClientConnectionManager(sr, socketTimeOut, TimeUnit.SECONDS);
connectionManager.setDefaultMaxPerRoute(maxConnectPerHost);
connectionManager.setMaxTotal(maxConnection);
HttpParams params = new BasicHttpParams();
params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, connectTimeOut);
params.setParameter(ClientPNames.COOKIE_POLICY, cookiePolicy);
params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, redirect);
params.setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, false);
if (isAutoRetry) {
client = new AutoRetryHttpClient(new DefaultHttpClient(connectionManager, params));
} else {
client = new DefaultHttpClient(connectionManager, params);
}
}
and then use the client to send request. The client should be a singleton. Here is the doGet method. And the connection should not be released.
public HttpResponse doGet(String url, List<Header> headers)
throws Exception {
HttpGet get = new HttpGet(url);
if (headers != null) {
Header[] array = new Header[headers.size()];
headers.toArray(array);
get.setHeaders(array);
}
try {
HttpResponse resp = client.execute(get);
return resp;
} catch (Exception e) {
// throw something
}
}
Here is the request:
Client c = new Client(1024, 1024 * 1024, 10000, 10000, CookiePolicy.IGNORE_COOKIES, true, true);
HttpResponse r = null;
try {
r = c.doGet("your url", null);
} finally{
if (r != null) {
EntityUtils.consumeQuietly(r.getEntity());
}
}
// send request again. There is no https handshake in this time.
try {
r = c.doGet("your url", null);
} finally{
if (r != null) {
EntityUtils.consumeQuietly(r.getEntity());
}
}
The handshake will be slow down your application. So you should not close/release connection in each request.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.