Java 中的 HTTP 即发即忘
Fire and forget for HTTP in Java
我们正在实施我们自己的分析,因为我们公开了一个需要调用的 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("whosebug.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");
}
}
我用过这个:
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();
对于 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;
}
}
也就是
我们正在实施我们自己的分析,因为我们公开了一个需要调用的 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("whosebug.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");
}
}
我用过这个:
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();
对于 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;
}
}
也就是