クラウド内の多数のサーバーに対して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("");
}
}
-編集:使用されているライブラリを明確にします-
Apacheのhttpclientを使用しています。関連するpom.xmlセクションを次に示します。
<dependency>
<groupId>org.Apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<type>jar</type>
</dependency>
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);
Http Clientバージョン4.3以降を使用している場合、これを使用する必要があります。
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
HttpParamsは、新しいApache HTTPClientライブラリで非推奨になりました。 Lazが提供するコードを使用すると、非推奨の警告が表示されます。
HttpGetまたはHttpPostインスタンスの代わりにRequestConfigを使用することをお勧めします。
final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);
HttpClient APIを使用しているようですが、これについては何も知りませんが、コア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;
}
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);
}
}
}
Lazによる最高のアップを持つ上記の方法は、バージョン4.3以降では非推奨です。したがって、Request Config Objectを使用してから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オブジェクトを使用しました。接続マネージャーからの接続を待機するためのタイムアウトを設定するために、プロパティー「接続要求タイムアウト」を設定することもできます。
これは、上記の benvoliot によるコメントですでに言及されています。しかし、トップレベルの投稿をする価値はあると思います。確かに頭を悩ませるからです。他の人に役立つ場合に備えて、これを投稿しています。
簡単なテストクライアントを作成しましたが、その場合はCoreConnectionPNames.CONNECTION_TIMEOUT
タイムアウトが完全に機能します。サーバーが応答しない場合、リクエストはキャンセルされます。
ただし、実際にテストしようとしていたサーバーコード内では、同じコードがタイムアウトすることはありません。
HTTP接続(CoreConnectionPNames.SO_TIMEOUT
)ではなくソケット接続アクティビティ(CoreConnectionPNames.CONNECTION_TIMEOUT
)でタイムアウトするように変更すると、問題が修正されました。
また、Apacheのドキュメントを注意深く読んでください: http://hc.Apache.org/httpcomponents-core-ga/httpcore/apidocs/org/Apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT
言うビットに注意してください
このパラメーターは、特定のローカルアドレスにバインドされている接続にのみ適用できることに注意してください。
私が経験したすべての頭の傷を他の誰かが救うことを願っています。それはドキュメントを完全に読まないことを教えてくれます!
Opは後で、Apache Commons HttpClient 3.0.1を使用していると述べました。
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
client.getHttpConnectionManager().getParams().setSoTimeout(5000);
HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout
必要なタイムアウトも定義できます。