最近发生了请求超时的问题,查了点资料,记在这里。
转自:http://lanpishu.iteye.com/blog/451275
HttpClient在使用中有两个超时时间,是一直接触和使用的,由于上次工作中使用httpClient造成了系统悲剧的情况,特地对它的两个超时时间进行了小小的测试,在这里记录下。
测试版本为HttpClient——3.1
一:连接超时:connectionTimeout
1:指的是连接一个url的连接等待时间。
2:设置方法为:
public class TestHttpClientMain {
- /**
- * @param args
- */
- public static void main(String[] args) {
- HttpClient client = new HttpClient();
- HttpMethod method = new GetMethod(
- "http://test.com");
- client.getHttpConnectionManager().getParams()
- .setConnectionTimeout(3000);
- client.getHttpConnectionManager().getParams().setSoTimeout(3000);
- try {
- int statusCode = client.executeMethod(method);
- System.out.println(statusCode);
- byte[] responseBody = null;
- responseBody = method.getResponseBody();
- String result = new String(responseBody);
- System.out.println(result);
- } catch (HttpException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
3:测试的时候,将url改为一个不存在的url:“http://test.com”
4:超时时间3000ms过后,系统报出异常。
org.apache.commons.httpclient.ConnectTimeoutException: The host did not accept the connection within timeout of 3000 ms
- at org.apache.commons.httpclient.protocol.ReflectionSocketFactory.createSocket(ReflectionSocketFactory.java:155)
- at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:125)
- at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
- at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
- at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
- at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
二:读取数据超时:soTimeout
1:指的是连接上一个url,获取response的返回等待时间
2:设置方法
public class TestHttpClientMain {
- /**
- * @param args
- */
- public static void main(String[] args) {
- HttpClient client = new HttpClient();
- HttpMethod method = new GetMethod(
- "http://localhost:8080/firstTest.htm?method=test");
- client.getHttpConnectionManager().getParams()
- .setConnectionTimeout(3000);
- client.getHttpConnectionManager().getParams().setSoTimeout(2000);
- try {
- int statusCode = client.executeMethod(method);
- System.out.println(statusCode);
- byte[] responseBody = null;
- responseBody = method.getResponseBody();
- String result = new String(responseBody);
- System.out.println(result);
- } catch (HttpException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
3:测试的时候的连接url为我本地开启的一个url,http://localhost:8080/firstTest.htm?method=test
在我这个测试url里,当访问到这个链接时,线程sleep一段时间,来模拟返回response超时。
@RequestMapping(params = "method=test") //<——②
- public String testMethod(ModelMap model) {
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println("call testMethod method.");
- model.addAttribute("name", "test method");
- return "test";
- }
4:将读取response返回超时时间设的时间比那个sleep时间短之后,运行程序给出异常:
java.net.SocketTimeoutException: Read timed out
- at java.net.SocketInputStream.socketRead0(Native Method)
- at java.net.SocketInputStream.read(Unknown Source)
- at java.io.BufferedInputStream.fill(Unknown Source)
- at java.io.BufferedInputStream.read(Unknown Source)
- at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78)
- at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106)
- at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116)
- at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973)
- at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735)
ok,以后再写httpClient这两个超时时间一定要加上,不加就很可能悲剧的了。
=======================================================================
转自:http://lanpishu.iteye.com/blog/451275
前一阵子发现我写的一个定时任务有问题。具体情况是我用apache commons HttpClient读其他一组机器的文件进行处理。为了避免一个定时任务耗时太多,使用下面的代码进行超时设置
- client.getParams().setConnectionManagerTimeout(20 * 1000L); // 20秒
- client.getParams().setSoTimeout(20 * 1000); // 20秒
但是后来发现有时会有请求超过100秒的情况出现,而且没有超时。
开始觉得很奇怪,为什么不会超时呢,难道是参数设置不正确?
测试了很久都没有发现什么问题,在jsp使用Thread.sleep(30000)就可以触发超时出现。但是为什么实际运行中会有超过100秒而不触发超时的情况呢?
后来使用下面的jsp进行测试终于发现了一种可能的原因
- <%@page contentType="text/html" pageEncoding="GBK"%><%
- long start = System.currentTimeMillis();
- for (int i = 0; i < 12; i ++) {
- out.println("不要超时");
- out.flush();
- Thread.sleep(10000L); // 10秒
- }
- out.println(System.currentTimeMillis() - start);
- %>
原来SocketTimeout设置的超时是指指定时间内服务器端没有反应,而如果两次反应之间的时间间隔小于设置的值是不算超时的。想想也是,下载大文件的超时肯定不能拿整个时间来计算。
下面是文档中的说明
'http.socket.timeout': defines the socket timeout (SO_TIMEOUT) in milliseconds, which is
the timeout for waiting for data or, put differently, a maximum period inactivity between two
consecutive data packets). A timeout value of zero is interpreted as an infinite timeout. This
parameter expects a value of type java.lang.Integer. If this parameter is not set read operations
will not time out (infinite timeout).