Vertx中HttpClient的setTimeout坑

问题描述:

因为特殊原因,导致某一时间段的请求全部超时,当网络恢复正常后,后续的请求还是会继续超时,且服务端也不能再收到任务消息,只能重启客户端服务器。

代码贴示:

private static HttpClientHolder clientHolder = new HttpClientHolder();
public static HttpClient getHttpClient() {
	return clientHolder.get(VertxInstance.getInstance().getVertx(),
			() -> new HttpClientOptions()
					.setMaxPoolSize(ConfigManager.DEFAULT.getInteger(WebGlobals.SECTION_NAME,
					"maxPool", 10));
}

private static void pushMsgToWebServer(JsonObject pushMsgRequest) {
    HttpClient client = getHttpClient();
    
    // Specify both port and host name
    HttpClientRequest clientRequest = client.post(WebGlobals.PORT, WebGlobals.HOST,
            WLGlobals.CALLBACK_URL_PATH, response -> {...});
    clientRequest.exceptionHandler(e -> {
        logger.error(String.format("pushMsgToWebServer response exception:%s", e));
    });
    clientRequest.setTimeout(30000);
    ......
}

原因说明:

首先我们需要理解HttpClient创建连接过程原理:池+队列,setMaxPoolSize是创建一个连接池,还有一个未使用方法setMaxWaitQueueSize用于创建队列大小(默认-1,表示无限大)。
当池被用完之后,新的请求会放入队列里等待。那么如果池的链接一直不归还(closed)那么后面新来的包括已经在等待的则无法被执行。
然后我们再看setTimeout()这个方法源码:

  public synchronized HttpClientRequest setTimeout(long timeoutMs) {
    cancelOutstandingTimeoutTimer();
    currentTimeoutMs = timeoutMs;
    currentTimeoutTimerId = client.getVertx().setTimer(timeoutMs, id -> handleTimeout(timeoutMs));
    return this;
  }

我们当调用这个方法时候,就已经开始进行超时计时(并不是从发出消息那刻算),并且继续深入源码会发现,该方法并无归还链接的操作。
即:一开始池中链接如果超时,并不会被主动释放(服务端调用closed时候,连接会被动释放),则后面依旧继续超时。

解决方案

在创建HttpClientOptions时候设置.setIdleTimeout(),源码中解释如下:
Set the idle timeout, default time unit is seconds. Zero means don't timeout.This determines if a connection will timeout and be closed if no data is received within the timeout.If you want change default time unit, use setIdleTimeoutUnit(TimeUnit)
即超时后会主动关闭连接

引用

https://github.com/eclipse-vertx/vert.x/issues/1842

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值