Запрос HTTP-клиента Java с заданным таймаутом
Я хотел бы сделать BIT (встроенный в тесты) на несколько серверов в моем облаке. Мне нужен запрос на провал с большим таймаутом.
Как мне сделать это с помощью java?
Попытка сделать что-то вроде ниже не работает.
public class TestNodeAliveness {
public static NodeStatus nodeBIT(String elasticIP) throws ClientProtocolException, IOException {
HttpClient client = new DefaultHttpClient();
client.getParams().setIntParameter("http.connection.timeout", 1);
HttpUriRequest request = new HttpGet("http://192.168.20.43");
HttpResponse response = client.execute(request);
System.out.println(response.toString());
return null;
}
public static void main(String[] args) throws ClientProtocolException, IOException {
nodeBIT("");
}
}
- EDIT: уточнить, какая библиотека используется -
Я использую httpclient из apache, вот соответствующий раздел pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<type>jar</type>
</dependency>
Ответы
Ответ 1
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
...
// set the connection timeout value to 30 seconds (30000 milliseconds)
final HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
client = new DefaultHttpClient(httpParams);
Ответ 2
Если вы используете Http Client версии 4.3 и выше, вы должны использовать это:
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
Ответ 3
HttpParams устарела в новой библиотеке Apache HTTPClient. Использование кода, предоставленного Laz, приводит к предупреждениям об отказе.
Я предлагаю использовать RequestConfig вместо вашего экземпляра HttpGet или HttpPost:
final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);
Ответ 4
Похоже, вы используете API HttpClient, о котором я ничего не знаю, но вы можете написать что-то похожее на это с помощью ядра Java.
try {
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod("HEAD");
con.setConnectTimeout(5000); //set timeout to 5 seconds
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
} catch (java.net.SocketTimeoutException e) {
return false;
} catch (java.io.IOException e) {
return false;
}
Ответ 5
Я обнаружил, что установка настроек тайм-аута в HttpConnectionParams
и HttpConnectionManager
не решила наш случай. Мы ограничены использованием org.apache.commons.httpclient
версии 3.0.1.
В итоге я использовал java.util.concurrent.ExecutorService
для отслеживания вызова HttpClient.executeMethod()
.
Здесь небольшой, автономный пример
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
/**
* @author Jeff Kirby
* @since <pre>Jun 17, 2011</pre>
*/
public class Example {
private static final String SITE = "http://some.website.com/upload";
private static final int TIME_OUT_SECS = 5;
// upload a file and return the response as a string
public String post(File file) throws IOException, InterruptedException {
final Part[] multiPart = { new FilePart("file", file.getName(), file) };
final EntityEnclosingMethod post = new PostMethod(SITE);
post.setRequestEntity(new MultipartRequestEntity(multiPart, post.getParams()));
final ExecutorService executor = Executors.newSingleThreadExecutor();
final List<Future<Integer>> futures = executor.invokeAll(Arrays.asList(new KillableHttpClient(post)), TIME_OUT_SECS, TimeUnit.SECONDS);
executor.shutdown();
if(futures.get(0).isCancelled()) {
throw new IOException(SITE + " has timed out. It has taken more than " + TIME_OUT_SECS + " seconds to respond");
}
return post.getResponseBodyAsString();
}
private static class KillableHttpClient implements Callable<Integer> {
private final EntityEnclosingMethod post;
private KillableHttpClient(EntityEnclosingMethod post) {
this.post = post;
}
public Integer call() throws Exception {
return new HttpClient().executeMethod(post);
}
}
}
Ответ 6
Указанный метод с наивысшим значением Laz устарел от версии 4.3 и далее. Следовательно, было бы лучше, если бы пользователь запросил объект конфигурации, а затем создал клиент HTTP
private CloseableHttpClient createHttpClient()
{
CloseableHttpClient httpClient;
CommonHelperFunctions helperFunctions = new CommonHelperFunctions();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(306);
cm.setDefaultMaxPerRoute(108);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(15000)
.setSocketTimeout(15000).build();
httpClient = HttpClients.custom()
.setConnectionManager(cm)
.setDefaultRequestConfig(requestConfig).build();
return httpClient;
}
PoolingHttpClientConnectionManager - это пользователь, который устанавливает максимальное количество подключений по умолчанию и максимальное количество подключений по маршруту. Я установил его как 306 и 108 соответственно. Значения по умолчанию не будут достаточными для большинства случаев.
Для настройки таймаута:
Я использовал объект RequestConfig. Вы также можете установить свойство Time Time Request Timeout для установки времени ожидания для подключения к диспетчеру соединений.
Ответ 7
Это уже упоминалось в комментарии benvoliot выше. Но, я думаю, это стоит должность высшего уровня, потому что я уверен, что я почесал голову. Я отправляю это на случай, если это поможет кому-то другому.
Я написал простой тестовый клиент, и тайм-аут CoreConnectionPNames.CONNECTION_TIMEOUT
отлично работает в этом случае. Запрос отменяется, если сервер не отвечает.
Внутри кода сервера я действительно пытался проверить, однако, идентичный код никогда не истекает.
Изменение времени ожидания активности подключения сокета (CoreConnectionPNames.SO_TIMEOUT
), а не HTTP-соединение (CoreConnectionPNames.CONNECTION_TIMEOUT
), устранило проблему для меня.
Также внимательно прочитайте документы Apache: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT
Обратите внимание на бит, который говорит
Обратите внимание, что этот параметр может применяться только к соединениям, привязанным к определенному локальному адресу.
Я надеюсь, что это спасет кого-то еще всю царапину головы, через которую я прошел. Это научит меня не полностью читать документацию.
Ответ 8
HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout
Вы также можете определить свой необходимый тайм-аут.
Ответ 9
Op позже заявили, что использовали Apache Commons HttpClient 3.0.1
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
client.getHttpConnectionManager().getParams().setSoTimeout(5000);