问题反馈
接到有客户反馈,在批量putobject时,发现上传到一定数量后应用卡住了,同时句柄数增加明显。
客户表示
1.使用10个worker线程进行put操作。
2.每个线程独立使用OssClient。
3.OssClient没有执行shutdown
排查过程
根据客户的描述,写了一个类似的程序来进行复现
开启五个线程,每个线程上传10000次object来测试
代码片段:
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
RunnableDemo R3 = new RunnableDemo( "Thread-3");
R3.start();
RunnableDemo R4 = new RunnableDemo( "Thread-4");
R4.start();
RunnableDemo R5 = new RunnableDemo( "Thread-5");
R5.start();
}
public void run() {
System.out.println("Running " + threadName );
for(int i = 0; i < 10000; i++) {
try {
System.out.println("Thread: " + threadName + ", " + i);
//上传部分
String content = new String();
content="12345";
// 创建上传Object的Metadata
ObjectMetadata meta = new ObjectMetadata();
// 设置上传文件长度
meta.setContentLength(content.length());
// 设置上传MD5校验
String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes()));
meta.setContentMD5(md5);
// 设置上传内容类型
meta.setContentType("text/plain");
meta.setServerSideEncryption("AES256");
// 上传文件
PutObjectRequest putObjectRequest=new PutObjectRequest("ruide", "1.txt", new ByteArrayInputStream(content.getBytes()), meta);
PutObjectResult por = ossclient.putObject(putObjectRequest);
System.out.println("requestid:"+por.getRequestId());
Thread.sleep(0);
}catch (Exception e) {
System.out.println("Thread " + threadName + " interrupted.");
}
}
System.out.println("Thread " + threadName + " exiting.");
}
测试5W次上传请求正常。
而在增加callback后出现了问题
PutObjectRequest putObjectRequest=new PutObjectRequest("ruide", "1.txt", new ByteArrayInputStream(content.getBytes()), meta);
Callback callback = new Callback();
callback.setCallbackUrl("http://xx.xxx.xx.xx/Revice.ashx");
callback.setCallbackBody("bucket:${bucket},size:${size}");
putObjectRequest.setCallback(callback);
PutObjectResult por = ossclient.putObject(putObjectRequest);
总结
看到上传确实卡住了。减少到1个线程,依然如此,看来并非是线程导致。
在putobject上传的时候,同时也会看到javaw进程的句柄数不断增加。
通过和OSS后端同学确认,在putobject时,如果没有callback是不需要句柄开销的。但如果
PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
即使不显性的read,那么也会产生句柄开销。而目前的句柄数是1000,当句柄数用完也就无法分配新的句柄导致程序卡住。需要增加
putObjectResult.getCallbackResponseBody().close();
添加后测试,测试OK
相关文档说明见https://help.aliyun.com/document_detail/32013.html