Java 如何在抓取大量小文件时优化HTTPClient性能?
我只想抓取一些黑客新闻故事和我的代码:Java 如何在抓取大量小文件时优化HTTPClient性能?,java,web-crawler,httpclient,Java,Web Crawler,Httpclient,我只想抓取一些黑客新闻故事和我的代码: import org.apache.http.client.fluent.Request; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.logging.Logger; import java.util.stream.IntStream; public class HackCraw
import org.apache.http.client.fluent.Request;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;
import java.util.stream.IntStream;
public class HackCrawler {
private static String getUrlResponse(String url) throws IOException {
return Request.Get(url).execute().returnContent().asString();
}
private static String crawlItem(int id) {
try {
String json = getUrlResponse(String.format("https://hacker-news.firebaseio.com/v0/item/%d.json", id));
if (json.contains("\"type\":\"story\"")) {
return json;
}
} catch (IOException e) {
System.out.println("crawl " + id + " failed");
}
return "";
}
public static void main(String[] args) throws FileNotFoundException {
Logger logger = Logger.getLogger("main");
PrintWriter printWriter = new PrintWriter("hack.json");
for (int i = 0; i < 10000; i++) {
logger.info("batch " + i);
IntStream.range(12530671 - (i + 1) * 100, 12530671 - i * 100)
.parallel()
.mapToObj(HackCrawler::crawlItem).filter(x -> !x.equals(""))
.forEach(printWriter::println);
}
}
}
import org.apache.http.client.fluent.Request;
导入java.io.FileNotFoundException;
导入java.io.IOException;
导入java.io.PrintWriter;
导入java.util.logging.Logger;
导入java.util.stream.IntStream;
公共类爬虫{
私有静态字符串getUrlResponse(字符串url)引发IOException{
return Request.Get(url.execute().returnContent().asString();
}
私有静态字符串爬网项(int-id){
试一试{
String json=getUrlResponse(String.format(“https://hacker-news.firebaseio.com/v0/item/%d.json“,id));
if(json.contains(“\”type\:\”story\”){
返回json;
}
}捕获(IOE异常){
System.out.println(“爬网”+id+“失败”);
}
返回“”;
}
公共静态void main(字符串[]args)引发FileNotFoundException{
Logger Logger=Logger.getLogger(“主”);
PrintWriter PrintWriter=newprintWriter(“hack.json”);
对于(int i=0;i<10000;i++){
logger.info(“批次”+i);
IntStream.范围(12530671-(i+1)*10012530671-i*100)
.parallel()
.mapToObj(HackCrawler::crawleItem).filter(x->!x.equals(“”)
.forEach(printWriter::println);
}
}
}
现在,抓取100(1批)个项目需要3秒钟
我发现通过并行使用多线程可以提高速度(大约5倍),但我不知道如何进一步优化它
有谁能提出一些建议吗 以下步骤应该可以让您开始
使用单个线程从站点获取响应,因为这基本上是一个IO操作
将这些响应放入队列(了解BlockingQueue的各种实现)
现在,您可以有多个线程来获取这些响应,并根据需要处理它们
基本上,您将拥有一个生产者线程,从站点和处理这些响应的多个消费者那里获取响应。为了实现Fayaz的意思,我将使用Jetty Http客户端异步功能()
该客户机在内部使用JavaNIO侦听传入的响应,每个连接只有一个线程。然后,它将内容分派给不涉及任何阻塞I/O操作的工作线程
您可以尝试使用每个目的地的最大连接数(目的地基本上是主机)
由于单个服务器的负载很重,这应该是相当高的。但是我已经通过parallel()
尝试了多线程。。。通过BlockingQueue进行多线程处理是否会神奇地提高性能?在您的方法中,您正在生成多个线程,每个线程同时执行获取响应和处理响应的任务。我认为这不是推荐的方法。您的问题是典型的生产者-消费者问题。我已经查看了Jetty HttpClient的文档,但是我找不到任何关于连接管理的内容(我认为保持活动状态
将提高性能),您对此有何想法?在HTTP 1.1中,默认情况下连接是持久的
httpClient.newRequest("http://domain.com/path")
.send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
// Your logic here
}
});