问题出现:之前上线过一个功能,使用Httpclient请求接口上传文件,线上使用情况反映功能响应很慢,具体核心代码如下:
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(webserver);
// 以浏览器兼容模式运行,防止文件名乱码。
HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addPart("file", new FileBodyImple(new File("D:/my_id.txt"))) // uploadFile对应服务端类的同名属性<File类型>
.setCharset(CharsetUtils.get("UTF-8")).build();
httpPost.setEntity(reqEntity);
// 发起请求 并返回请求的响应
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
}
// 销毁
EntityUtils.consume(resEntity);
} catch (IOException e) {
e.printStackTrace();
} finally {
response.close();
}
} finally {
httpClient.close();
}
超级正常的一段代码,但是文件大小超过5M后请求时间大概在30s左右,以为是接口问题,但是通过postman进行接口测试之后发现响应速度正常。但是在其余项目中运行此代码响应速度正常。
以为是某个jar包问题,于是重新创建了一个新的项目,pom文件与此项目pom文件一致,发现响应速度正常。
经过debug代码,发现在FileBody类下面
public void writeTo(final OutputStream out) throws IOException {
Args.notNull(out, "Output stream");
final InputStream in = new FileInputStream(this.file);
try {
final byte[] tmp = new byte[4096];
int l;
while ((l = in.read(tmp)) != -1) {
out.write(tmp, 0, l);
}
out.flush();
} finally {
in.close();
}
}
此方法中out.write请求时间过长,再经过层层debug代码,最终发现在Wirte类下面
private void wire(String header, InputStream instream) throws IOException {
StringBuilder buffer = new StringBuilder();
while(true) {
int ch;
while((ch = instream.read()) != -1) {
if (ch == 13) {
buffer.append("[\\r]");
} else if (ch == 10) {
buffer.append("[\\n]\"");
buffer.insert(0, "\"");
buffer.insert(0, header);
this.log.debug(this.id + " " + buffer.toString());
buffer.setLength(0);
} else if (ch >= 32 && ch <= 127) {
buffer.append((char)ch);
} else {
buffer.append("[0x");
buffer.append(Integer.toHexString(ch));
buffer.append("]");
}
}
if (buffer.length() > 0) {
buffer.append('"');
buffer.insert(0, '"');
buffer.insert(0, header);
this.log.debug(this.id + " " + buffer.toString());
}
return;
}
}
注意注意!!!this.log.debug(this.id+" "+buffer.toString());我擦擦擦,这是什么鬼,打印debug级别日志,果不其然,我去debug日志文件里查看,果然看到此文件。。。最终去查看logger配置文件,果不其然,输出的是debug级别的日志。
到此,此问题被完美解决,修改下日志级别。
这个bug,用了3天业余时间才发现。最开始的时候以为是OSS(阿里云文件存储)慢,因为没有接触过OSS,所以先简单了解下OSS,中间遇到过配置文件中OSS域名是内网,所以在本地代码怎么测试都不行,最后才发现应该改域名,改完测试发现不是对方接口的问题。
然后发现上传的不是txt文件的就可以,最后的话才是层层打断点,不断深入httpclient.excutor()内部,最后才了解到问题的所在