Java中HTTP的Fire and forget
我们正在实现我们自己的分析,我们已经公开了一个需要调用的web服务,它将捕获数据库中的数据 问题是,由于这是分析,我们会进行很多调用(比如每次页面加载、每次js后的调用、CSS加载等),因此会有很多这样的调用。因此,我不希望服务器加载大量的请求,以便更精确地等待响应。因为我们得到的回应对我们几乎没有任何用处 那么,有没有什么方法可以直接启动web服务请求,而忘记我已经启动了它 我知道每个HTTP请求也会有响应 所以有一件事让我感到不安,那就是如果我们让请求超时到零秒怎么办?但我不确定这是不是正确的方法Java中HTTP的Fire and forget,java,httprequest,httpclient,analytics,httpresponse,Java,Httprequest,Httpclient,Analytics,Httpresponse,我们正在实现我们自己的分析,我们已经公开了一个需要调用的web服务,它将捕获数据库中的数据 问题是,由于这是分析,我们会进行很多调用(比如每次页面加载、每次js后的调用、CSS加载等),因此会有很多这样的调用。因此,我不希望服务器加载大量的请求,以便更精确地等待响应。因为我们得到的回应对我们几乎没有任何用处 那么,有没有什么方法可以直接启动web服务请求,而忘记我已经启动了它 我知道每个HTTP请求也会有响应 所以有一件事让我感到不安,那就是如果我们让请求超时到零秒怎么办?但我不确定这是不是正确
请提供更多建议是的,您可以启动请求并中断连接,而无需等待响应但是你可能不想那样做。服务器端处理不正常断开的连接的开销将远远超过让它继续返回响应的开销
在Java servlet中解决此类性能问题的更好方法是将请求中的所有数据推送到队列中,立即响应,并让一个或多个工作线程从队列中提取项目进行处理(例如将其写入数据库).您可能会发现以下
AsyncRequestDemo.java
非常有用:
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.http.client.fluent.Async;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.concurrent.FutureCallback;
/**
* Following libraries have been used:
*
* 1) httpcore-4.4.5.jar
* 2) httpclient-4.5.2.jar
* 3) commons-logging-1.2.jar
* 4) fluent-hc-4.5.2.jar *
*
*/
public class AsyncRequestDemo {
public static void main(String[] args) throws Exception {
URIBuilder urlBuilder = new URIBuilder()
.setScheme("http")
.setHost("stackoverflow.com")
.setPath("/questions/38277471/fire-and-forget-for-http-in-java");
final int nThreads = 3; // no. of threads in the pool
final int timeout = 0; // connection time out in milliseconds
URI uri = null;
try {
uri = urlBuilder.build();
} catch (URISyntaxException use) {
use.printStackTrace();
}
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
Async async = Async.newInstance().use(executorService);
final Request request = Request.Get(uri).connectTimeout(timeout);
Future<Content> future = async.execute(request, new FutureCallback<Content>() {
public void failed(final Exception e) {
System.out.println("Request failed: " + request);
System.exit(1);
}
public void completed(final Content content) {
System.out.println("Request completed: " + request);
System.out.println(content.asString());
System.exit(0);
}
public void cancelled() {
}
});
System.out.println("Request submitted");
}
}
导入java.net.URI;
导入java.net.URISyntaxException;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
导入org.apache.http.client.fluent.Async;
导入org.apache.http.client.fluent.Content;
导入org.apache.http.client.fluent.Request;
导入org.apache.http.client.utils.URIBuilder;
导入org.apache.http.concurrent.FutureCallback;
/**
*已使用以下库:
*
*1)httpcore-4.4.5.jar
*2)httpclient-4.5.2.jar
*3)commons-logging-1.2.jar
*4)fluent-hc-4.5.2.jar*
*
*/
公共类AsyncRequestDemo{
公共静态void main(字符串[]args)引发异常{
URIBuilder urlBuilder=新的URIBuilder()
.setScheme(“http”)
.setHost(“stackoverflow.com”)
.setPath(“/questions/38277471/fire and forget for http in java”);
final int nThreads=3;//池中的线程数
final int timeout=0;//连接超时(毫秒)
URI=null;
试一试{
uri=urlBuilder.build();
}捕获(URISyntaxException使用){
使用.printStackTrace();
}
ExecutorService ExecutorService=Executors.newFixedThreadPool(nThreads);
Async Async=Async.newInstance().use(executorService);
最终请求=Request.Get(uri).connectTimeout(超时);
Future=async.execute(请求,new FutureCallback(){
公共作废失败(最终异常e){
System.out.println(“请求失败:+请求”);
系统出口(1);
}
已完成公共作废(最终内容){
System.out.println(“请求完成:+请求”);
System.out.println(content.asString());
系统出口(0);
}
公众假期取消(){
}
});
System.out.println(“提交的请求”);
}
}
我用了这个:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
URL url = new URL(YOUR_URL_PATH, "UTF-8"));
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<HttpResponse> response = executor.submit(new HttpRequest(url));
executor.shutdown();
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
URL=新URL(您的URL路径“UTF-8”);
ExecutorService executor=Executors.newFixedThreadPool(1);
未来响应=executor.submit(新的HttpRequest(url));
executor.shutdown();
对于HttpRequest,HttpResponse
public class HttpRequest implements Callable<HttpResponse> {
private URL url;
public HttpRequest(URL url) {
this.url = url;
}
@Override
public HttpResponse call() throws Exception {
return new HttpResponse(url.openStream());
}
}
public class HttpResponse {
private InputStream body;
public HttpResponse(InputStream body) {
this.body = body;
}
public InputStream getBody() {
return body;
}
}
公共类HttpRequest实现可调用{
私有URL;
公共HttpRequest(URL){
this.url=url;
}
@凌驾
公共HttpResponse调用()引发异常{
返回新的HttpResponse(url.openStream());
}
}
公共类HttpResponse{
私有输入流体;
公共HttpResponse(输入流体){
这个身体=身体;
}
公共输入流getBody(){
返回体;
}
}
也就是说。“开销。。。将远远超过“为什么?”?为什么不能通过网络发送数据比通过网络发送数据更糟糕呢?因为Java将引发异常、生成堆栈跟踪等等。。。这是必须处理的。如果关注的是性能,那么成本就会很高。连接/握手已经建立,因此完成响应(即使是空响应)比断开连接更安全。顺便说一句,我没说你做不到。我说你可能不想。每次你想记录一个事件,而不是做一个调用,收集事件数据并减少调用。在某个时候你可以考虑UDP来解决这个问题。这个解决方案比我想的要好,但是仍然有12个线程(或者任何线程池大小)。这里的问题是,我们使用它进行分析,所以我们需要提供大量的请求。我们能想点别的吗?可能是大小为n的线程池将网络超时设置为零?Hi@GokulKulkarni这两个方面i)
大小为n的线程池和ii)网络超时已包含在答案中。请看一看,在这个方法中,我们关闭了执行器,但是我假设线程仍然会等待响应,因为HTTP就是这样设计的。以下是有助于理解基础知识的两个链接:1。2.