|
vert HttpClient性能非常好,但是使用不当,就会出现非常难于定位的问题。很多问题非常严重,比如挂死,分析日志、堆栈都可能看不出任何原因。因此在写代码的时候,就需要非常注意。下面有几个排查点:
-
设置请求超时时间。必须合理设计超时时间,否则异常情况,会导致连接不释放。如果在response里面做其他操作,还需要重设超时时间。
例如:
HttpClientRequest clietRequest =
httpClient.request(context.request().method(),
uri.getPort(),
uri.getHost(),
"/" + path + params).setTimeout(10000); //设置请求超时时间
clietRequest.handler(clientResponse -> {
clietRequest.setTimeout(10000); //如果解析响应还可能超时,那么也必须重设超时时间
context.request().response().setStatusCode(clientResponse.statusCode());
context.request().response().headers().setAll(clientResponse.headers());
LOGGER.info("remote response begins");
clientResponse.handler(data -> {
context.request().response().write(data);
LOGGER.info("remote response data transfer");
});
clientResponse.endHandler((v) -> {
context.request().response().end();
LOGGER.info("remote response data transfer end");
});
clientResponse.exceptionHandler(e -> {
LOGGER.info("e", e);
});
});
2. 设置闲置超时时间和最大队列大小。如果不设置,也可能导致连接不释放。新进来请求没有连接可用,造成等待挂死。需要注意的是,闲置超时时间的单位是秒,和其他接口不同。如果不看文档,肯定就弄错了。
vertx.createHttpClient(
new HttpClientOptions().setSsl(false)
.setVerifyHost(false)
.setTrustAll(true)
.setKeepAlive(true)
.setConnectTimeout(2000)
.setIdleTimeout(10)// 闲置超时时间
.setMaxWaitQueueSize(10)); //最大队列大小
3. 设置exceptionHandler。request和response都需要设置合理的异常处理,以跟踪错误。
clietRequest.exceptionHandler(e -> {
LOGGER.error("xxxxx", e);
context.response().end();
});
clietRequest.connectionHandler(h -> {
h.exceptionHandler(eh -> {
LOGGER.error("conn", eh);
});
LOGGER.info("connection " + h);
});
在上述代码中,还有个坑
context.request().response().headers().setAll(clientResponse.headers());
将一个请求的响应头全部拷贝到另外一个响应的头中(看起来是纯粹的HTTP转发)。这个操作是不对的。因为有些响应头是HTTP的控制消息,比如:Content-Length, Transfer-Encoding。一旦将两个头拷贝进去,就可能影响到HTTP报文的完整性(丢失或者多出额外的字节)。代码需要做一些特殊处理,不要拷贝这两个头。
|