У меня есть приложение, которое висит на FileOutputStream.close()
(ну, действительно, оно висит на нативном FileOutputStream.close0()
, но неважно).И ... я действительно не знаю, что могло бы вызвать это.Как эксперт по отладке Java / Linux может решить эту проблему?
Я использовал jstack
, чтобы найти место преступления, и вот оно:
s3-transfer-manager-worker-1" #22 prio=5 os_prio=0 tid=0x00007f9f40007800 nid=0x2e6 runnable [0x00007f9fac4d7000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.close0(Native Method)
at java.io.FileOutputStream.access$000(FileOutputStream.java:53)
at java.io.FileOutputStream$1.close(FileOutputStream.java:356)
at java.io.FileDescriptor.closeAll(FileDescriptor.java:212)
- locked <0x00000005c3bbc440> (a java.io.FileDescriptor)
at java.io.FileOutputStream.close(FileOutputStream.java:354)
at sun.nio.ch.FileChannelImpl.implCloseChannel(FileChannelImpl.java:139)
at java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:115)
- locked <0x00000005c3bbc600> (a java.lang.Object)
at com.amazonaws.util.IOUtils.closeQuietly(IOUtils.java:70)
at com.amazonaws.services.s3.internal.ServiceUtils.appendFile(ServiceUtils.java:473)
at com.amazonaws.services.s3.transfer.internal.CompleteMultipartDownload.call(CompleteMultipartDownload.java:46)
at com.amazonaws.services.s3.transfer.internal.CompleteMultipartDownload.call(CompleteMultipartDownload.java:29)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Загрузить код
Вот упрощенная версия нашего кода загрузки S3:
AmazonS3Client s3Client = new AmazonS3Client(new DefaultAWSCredentialsProviderChain());
s3Client.setRegion(...);
TransferManager s3TransferManager = TransferManagerBuilder.standard().withS3Client(s3Client).build();
GetObjectRequest objectRequest = new GetObjectRequest(...);
Path localTempFile = Files.createTempFile(...);
Download downloadHandle = s33TransferManager.download(objectRequest, localTempFile.toFile());
downloadHandle.waitForCompletion();
Довольно ваниль.
Фон
Это довольно ванильное использование Java AWS S3API для загрузки файла на локальный диск.Я могу скачать тот же файл, используя приложение aws s3 cp ...
командной строки просто отлично.Еще более запутанно то, что приложение раньше работало просто отлично.У него есть около 1000 таких файлов для загрузки, и он прошел через 11 из них, прежде чем это начало происходить.
Вещи, которые я знаю:
- Это мощные файлы, около 20 ГБкаждый.
- Я пробовал несколько раз, и оставил его там на 1:00 и в последнее время на 2:00.Он остается зависшим.
- У нас достаточно свободного дискового пространства: 200 ГБ.(И все равно было бы исключение, если бы это было проблемой.)
- Я попытался выключить и снова включить (через
sudo reboot
). - Это
m4.2xlarge
Экземпляр EC2. - В CloudWatch процессор не занят.
- Я могу загрузить точно такой же файл из S3 в точно такое же местоположение с помощью командной строки
aws s3 cp ...
, которая управляетout: - Проблемы с дисковым пространством (снова).
- Нехватка IOPS (если только Java SDK
TransferManager
не делает что-то совсем другое и глупое). - Действительно медленные загрузки:загрузка файла из командной строки занимает около 5 минут.
- Проблемы с правами доступа к файлу.
Следующие шаги?
К сожалениюЯ не знаю достаточно, чтобы пойти дальше, чем в отладке этого.Существуют ли конкретные метрики или команды Linux, которые я должен проверять, чтобы увидеть, не исчерпан ли или не заблокирован ли какой-либо системный ресурс?