Java HttpClient似乎正在缓存内容
我正在构建一个简单的web scraper,我需要获取相同的页面数百次,页面中有一个动态属性,应该在每次请求时更改。我构建了一个基于多线程HttpClient的类来处理请求,并使用Java HttpClient似乎正在缓存内容,java,multithreading,http,get,httpclient,Java,Multithreading,Http,Get,Httpclient,我正在构建一个简单的web scraper,我需要获取相同的页面数百次,页面中有一个动态属性,应该在每次请求时更改。我构建了一个基于多线程HttpClient的类来处理请求,并使用ExecutorService创建一个线程池并运行线程。问题是,动态属性有时不会在每个请求上更改,我最终会在后续的3或4个线程上获得相同的值。我已经读了很多关于HttpClient的书,但我真的不知道这个问题是从哪里来的。这可能是关于缓存的事情,还是类似的事情 更新:以下是每个线程中执行的代码: HttpContext
ExecutorService
创建一个线程池并运行线程。问题是,动态属性有时不会在每个请求上更改,我最终会在后续的3或4个线程上获得相同的值。我已经读了很多关于HttpClient的书,但我真的不知道这个问题是从哪里来的。这可能是关于缓存的事情,还是类似的事情
更新:以下是每个线程中执行的代码:
HttpContext localContext = new BasicHttpContext();
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
ClientConnectionManager connman = new ThreadSafeClientConnManager();
DefaultHttpClient httpclient = new DefaultHttpClient(connman, params);
HttpHost proxy = new HttpHost(inc_proxy, Integer.valueOf(inc_port));
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
proxy);
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("User-Agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
String iden = null;
int timeoutConnection = 10000;
HttpConnectionParams.setConnectionTimeout(httpGet.getParams(),
timeoutConnection);
try {
HttpResponse response = httpclient.execute(httpGet, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String result = convertStreamToString(instream);
// System.out.printf("Resultado\n %s",result +"\n");
instream.close();
iden = StringUtils
.substringBetween(result,
"<input name=\"iden\" value=\"",
"\" type=\"hidden\"/>");
System.out.printf("IDEN:%s\n", iden);
EntityUtils.consume(entity);
}
}
catch (ClientProtocolException e) {
// TODO Auto-generated catch block
System.out.println("Excepção CP");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Excepção IO");
}
HttpContext localContext=new BasicHttpContext();
HttpParams params=新的BasicHttpParams();
HttpProtocolParams.setVersion(params,HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(参数,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params,true);
ClientConnectionManager connman=新的ThreadSafeClientConnManager();
DefaultHttpClient httpclient=新的DefaultHttpClient(connman,params);
HttpHost proxy=新的HttpHost(inc_proxy,Integer.valueOf(inc_端口));
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_代理、,
委托书);
HttpGet HttpGet=新的HttpGet(url);
setHeader(“用户代理”,
“Mozilla/4.0(兼容;MSIE 6.0;Windows NT 5.1)”;
字符串iden=null;
int timeoutConnection=10000;
HttpConnectionParams.setConnectionTimeout(httpGet.getParams(),
超时连接);
试一试{
HttpResponse response=httpclient.execute(httpGet,localContext);
HttpEntity=response.getEntity();
如果(实体!=null){
InputStream instream=entity.getContent();
字符串结果=convertStreamToString(流内);
//System.out.printf(“Resultado\n%s”,result+“\n”);
流内关闭();
iden=StringUtils
.substringBetween(结果,
"");
System.out.printf(“IDEN:%s\n”,IDEN);
EntityUtils.consume(实体);
}
}
捕获(客户端协议例外e){
//TODO自动生成的捕捉块
System.out.println(“Excepço CP”);
}捕获(IOE异常){
//TODO自动生成的捕捉块
System.out.println(“例外”);
}
一般来说,为了测试HTTP请求是否通过网络发出,您可以使用分析网络流量的“嗅探”工具,例如:
- Fiddler()-我从这个开始
- Wireshark()-更低级别
我希望这能给你一个起点。如果您已经考虑过这些方法,那就太好了。您可以尝试在每个请求的URL中添加一些唯一的伪参数,以尝试阻止任何基于URL的缓存(在服务器中或在某个地方)。如果缓存不是问题,或者如果服务器足够聪明,可以拒绝具有未知参数的请求,或者如果服务器正在缓存但仅基于其关心的参数,或者如果您选择的参数名称与站点实际使用的参数冲突,则该方法将不起作用 如果这是您正在使用的URL 试用
为每个请求将dummy设置为不同的值。HTTPClient默认情况下不使用缓存(仅当您使用
DefaultHttpClient
类时)。如果您使用CachingHttpClient
即HttpClient
接口装饰器启用缓存,则会执行此操作:
HttpClient client = new CachingHttpClient(new DefaultHttpClient(), cacheConfiguration);
然后,它分析是否自
修改,以及是否不匹配
头,以确定是否执行对远程服务器的请求,或者其结果是否从缓存返回
我怀疑,您的问题是由位于应用程序和远程服务器之间的代理服务器引起的
您可以使用curl
应用程序轻松测试它;执行一些忽略代理的请求数:
#!/bin/bash
for i in {1..50}
do
echo "*** Performing request number $i"
curl -D - http://yourserveraddress.com -o $i -s
done
然后,在所有下载的文件之间执行
diff
。他们都应该有你提到的不同之处。然后,将-x/--proxy
选项添加到curl,执行此脚本并再次比较文件。如果某些响应与其他响应相同,则可以确定这是代理服务器问题。可以缓存在服务器端。您可能正在编写线程不安全代码,并且每当下载数据时,旧结果都会被新结果覆盖。没有代码很难判断。我已经用代码更新了问题。我还使用FixedThreadPool来执行线程:ExecutorService pool=Executors.newFixedThreadPool(10);对于(int i=0;i