我做了什么:
我使用vertx rx http客户端来执行大量HTTP请求。在这个特定的情况下,我调用“方法A”,它返回一个ID列表。接收我需要多次调用方法A的所有ID以获得下一批结果。 (每次我指定一个不同的页码我想收到)
为了提高性能并尽可能并行地进行调用,我创建了一个(RxJava)Observables项目列表,每个项目代表单个页面请求的结果。当我完成创建此列表时,我调用Obserable.zip运算符并传递observable列表。
问题:
使用没有特殊设置的vertx http客户端一切正常但非常慢。例如3000个http请求将在5分钟内处理完毕。
我尝试通过设置vertx http客户端选项来提高性能,如下所示:
HttpClientOptions options = new HttpClientOptions();
options.setMaxPoolSize(50)
.setKeepAlive(true)
.setPipelining(true)
.setTcpKeepAlive(true)
.setPipeliningLimit(25)
.setMaxWaitQueueSize(10000);
但是当我这样做时,我会得到不稳定的结果:有时一切正常,我能够在不到20秒的时间内收到所有回复。但是,有时我调用的外部服务器关闭连接,日志显示以下错误:
io.vertx.core.http.impl.HttpClientRequestImpl
SEVERE: io.vertx.core.VertxException: Connection was closed
以下是创建HttpClientRequest
的代码public Observable<HttpRestResponse> postWithResponse(String url, Map<String, String> headers, String body) {
Observable<HttpRestResponse> bufferObservable = Observable.create(subscriber -> {
try {
HttpClientRequest request = httpClient.postAbs(url);
addHeadersToRequest(headers, request);
sendRequest(url, subscriber, request, body);
}catch (Exception e) {
try {
subscriber.onError(e);
}catch (Exception ex) {
logger.error("error calling onError for subscriber",ex);
}finally {
subscriber.onCompleted();
}
}
});
return bufferObservable;
}
private void sendRequest(String requestUrl, Subscriber<? super HttpRestResponse> subscriber, HttpClientRequest request, String bodyData) {
final long requestId = reqNumber.getAndIncrement();
if (bodyData != null) {
request.putHeader("Content-Length", String.valueOf(bodyData.getBytes().length);
}
request.putHeader("Accept-Encoding", "gzip,deflate");
Observable<HttpRestResponse> retVal = request.toObservable()
.doOnError(throwable -> {
logger.error("<<< #: " + requestId + " HTTP call failed. requestUrl [" + requestUrl + "] reason:" + throwable.getMessage());
}).doOnNext(response -> {
if (response != null) {
logger.debug(" <<< #: " + requestId + " " + response.statusCode() + " " + response.statusMessage() + " " + requestUrl);
}
}).flatMap(httpClientResponse -> {
try {
if (httpClientResponse != null && doCheckResponse(httpClientResponse, requestUrl, requestId, bodyData)) {
Observable<Buffer> bufferObservable = httpClientResponse.toObservable()
.reduce(Buffer.buffer(1000), (result, buffer) -> result.appendBuffer(buffer));
return bufferObservable.flatMap(buffer -> Observable.just(new HttpRestResponse(buffer, httpClientResponse)));
}
} catch (Exception e) {
logger.error("error in RestHttpClient", e);
}
return Observable.just(new HttpRestResponse(null, httpClientResponse));
});
retVal.subscribe(subscriber);
if (bodyData != null) {
request.end(bodyData); // write post data
} else {
request.end();
}
}
asdasdasd
答案 0 :(得分:0)
如果您认为可以像这样挂钩您的异常逻辑
try {
HttpClientRequest request = httpClient.postAbs(url);
addHeadersToRequest(headers, request);
sendRequest(url, subscriber, request, body);
}catch (Exception e) {
try {
subscriber.onError(e);
}catch (Exception ex) {
logger.error("error calling onError for subscriber",ex);
}finally {
subscriber.onCompleted();
}
}
您不会收到任何错误,因为基本上所有处理现在都停留在Rx生态系统中,因此您的try catch块中没有任何内容会报告给您。
从这个时间点出现的错误将来自你的
bufferObservable.onErrorReturn()
或
bufferObservable.subscribe(success, error)
答案 1 :(得分:0)
所以最后我想出来了。看来我把Observable.zip方法传递给了一个空列表...
这里的问题是onNext或onError没有在“zip”方法的返回的observable对象上调用。在这种情况下,只调用onComplete,我没有费心为...创建处理程序。
非常感谢所有感兴趣并希望提供帮助的人。
参见Yaniv