java中连接服务端接口超时,服务器诡异的请求超时问题

本文记录了一次线上服务请求超时的问题排查过程。问题表现为前端请求后端服务时出现两秒超时,但后端实际上完成了请求。通过对系统日志、IO使用状况的深入分析,发现一个名为`sas3flash`的HBA管理工具在执行时导致了IO堵塞,从而引发了超时。该工具属于腾讯云黑石监控组件的一部分,其`--list`命令通过ioctl调用导致了问题。目前,解决方案是禁止该命令的执行,等待腾讯云的修复更新。
摘要由CSDN通过智能技术生成

前些日子,监控显示线上偶尔发生请求两秒超时的情况。解决这个问题前前后后花了不少时间,也走了一些弯路。这里记录下来备忘。

前期分析

首先需要了解一下我们的服务:

我们的服务是一组无状态的前端服务器加上有状态的后端存储层。

这些服务都部署在腾讯云黑石服务器上面。

第一件事是要定位问题出现在前端还是后端。通过日志,我们发现在出错时间段里,每个前端服务器都有报错,并且出错请求都是发往同一后端服务器的。由此可见,问题出现在后端服务上。

接下来,需要分析出错的特征。通过日志发现错误都是因为前端两秒超时导致,而后端在前端超时之后事实上是完成了请求。因为是存储服务,我们自然在第一时间就查看了磁盘的情况。果然,在出错时,磁盘的io.util非常高(sar -dp的输出,从第4列开始分别是tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util):

741b9c4812c377cd504f264cdcadf604.png

需要注意的是:

io.util非常高,且只持续了2~3秒

几乎所有盘的io.util都高

io的tps和吞吐并不高

另外,还发现了另外一个规律:单台机器,大概每12小时左右会出现io.util高,并伴随着超时出错:

9ee50684f662c0fa502652ae98036956.png

问题排查

快速排查

我们做了一些快速排查,试图以比较小的代价找到问题的根源:

查看系统的定时任务

查看系统日志

查看存储服务代码中的定时任务

可惜,都没有发现有价值的线索。于是推测,一定是有一个我们不知道的存在以12小时为周期在消耗IO。

追踪IO使用状况

先使用iotop来定位出错时刻是谁占用了大量IO:

python /sbin/iotop -bPto -n 86400 > iotop.log

上述命令以批处理的形式,每1秒一个输出,一共持续86400秒(24小时)。同样,并没有发现除了我们程序之外的可疑线程。

Iotop虽然是一个好工具,然而一个缺陷是并没有详细的文档说明它的工作原理。对于一个系统工具来说,原理性的文档还是很有必要的。在这种情况下,我们怀疑iotop并不能真实的反映进程的IO使用状况。为了再次确认,我们采用SystemTap来统计IO调用。下面是改良过的iotop.stp:

global count_stacks

global size_stacks

g

Java设置HTTP服务端的读超时时间通常涉及到使用`HttpURLConnection`或者第三方库如`Apache HttpClient`或`OkHttp`。这里以`HttpURLConnection`为例,你可以通过创建连接时设置`SocketTimeout`属性来实现读操作的超时: ```java URL url = new URL("http://example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setReadTimeout(5000); // 设置超时时间为5秒,单位为毫秒 try { connection.connect(); // 连接服务器 // 从服务器读取数据... } catch (IOException e) { if (e instanceof SocketTimeoutException) { System.out.println("读取超时!"); } else { e.printStackTrace(); } } // 关闭连接 connection.disconnect(); ``` 如果你使用的是`Apache HttpClient`,可以在`CloseableHttpResponse`上设置连接管理器的超时: ```java HttpClient httpClient = HttpClients.createDefault(); HttpGet request = new HttpGet("http://example.com"); RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000).build(); CloseableHttpResponse response = httpClient.execute(request, config); try { // 读取响应... } finally { response.close(); } ``` 对于`OkHttp`, 在`OkHttpClient.Builder`添加`connectTimeout`和`readTimeout`: ```java OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(5000, TimeUnit.MILLISECONDS) .readTimeout(5000, TimeUnit.MILLISECONDS) .build(); Response response = client.newCall(new Request.Builder() .url("http://example.com") .build()) .execute(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值