Потоковые большие файлы в сервлете Java

API - это интерфейс, через который вы получаете доступ к коду elses или через который чужой код обращается к вашим. По сути, это общедоступные методы и свойства.

41
задан Steve Buikhuizen 11 September 2008 в 02:40
поделиться

7 ответов

Когда возможно, Вы не должны хранить все содержание файла, который будет подаваться в памяти. Вместо этого aquire InputStream для данных и копия данные к Сервлету OutputStream в частях. Например:

ServletOutputStream out = response.getOutputStream();
InputStream in = [ code to get source input stream ];
String mimeType = [ code to get mimetype of data to be served ];
byte[] bytes = new byte[FILEBUFFERSIZE];
int bytesRead;

response.setContentType(mimeType);

while ((bytesRead = in.read(bytes)) != -1) {
    out.write(bytes, 0, bytesRead);
}

// do the following in a finally block:
in.close();
out.close();

я действительно соглашаюсь с toby, необходимо вместо этого "указать на них на S3 url".

Что касается исключения OOM, действительно ли Вы уверены, что оно имеет отношение к обслуживанию данных изображения? Скажем, Ваша JVM имеет 256 МБ "дополнительной" памяти для использования для обслуживания данных изображения. Со справкой Google, "256 МБ / 200 КБ" = 1310. Для "дополнительной" памяти на 2 ГБ (в эти дни очень разумная сумма) могли поддерживаться более чем 10 000 одновременных клиентов. Несмотря на это, 1 300 одновременных клиентов довольно большое количество. Действительно ли это - тип загрузки, которую Вы испытали? В противном случае Вы, возможно, должны в другом месте искать причину исключения OOM.

Редактирование - Относительно:

В этом варианте использования изображения могут содержать уязвимые данные...

, Когда я прочитал документацию S3 несколько недель назад, я заметил, что можно генерировать истекающие время ключи, которые могут быть присоединены к URL S3. Так, Вы не должны были бы открывать файлы на S3 общественности. Мое понимание техники:

  1. Начальная страница HTML имеет ссылки на загрузку на Вашего Пользователя веб-приложения
  2. , нажимает на ссылку на загрузку
  3. , Ваше веб-приложение генерирует S3 URL, который включает ключ, который истекает в, позволяет, говорят, 5 минут.
  4. Отправляют перенаправление HTTP клиенту с URL от шага 3.
  5. , пользователь загружает файл с S3. Это работает, даже если загрузка занимает больше чем 5 минут - как только загрузка запускается, это может продолжиться посредством завершения.
54
ответ дан John Vasileff 11 September 2008 в 02:40
поделиться

Почему Вы только не указали бы на них на S3 url? Взятие артефакта от S3 и затем потоковая передача его через Ваш собственный сервер мне побеждают цель использовать S3, который должен разгрузить пропускную способность и обработку обслуживания изображений к Amazon.

17
ответ дан airportyh 11 September 2008 в 02:40
поделиться
  • 1
    @Tomasz_Nurkiewicz хорошо, обновил мой вопрос с предложением по настраиваемому решению. – basZero 21 March 2012 в 12:53

Я соглашаюсь сильно и с toby и с John Vasileff - S3 является большим для от загрузки больших мультимедийных объектов, если можно терпеть связанные проблемы. (Экземпляр собственного приложения делает это для 10-1000MB FLVs и MP4s.), Например: Никакие частичные запросы (заголовок диапазона байта), все же. Нужно обработать это 'вручную', случайное время простоя, и т.д.

, Если это не опция, код John выглядит хорошим. Я нашел, что буфер байта 2k FILEBUFFERSIZE является самым эффективным в метках микроместа размещения. Другой опцией мог бы быть общий FileChannel. (FileChannels ориентированы на многопотоковое исполнение.)

Однако я также добавил бы, что предположение, что вызвало из ошибки памяти, является классической ошибкой оптимизации. Вы улучшили бы свои шансы на успех путем работы с твердыми метриками.

  1. Место-XX: + HeapDumpOnOutOfMemoryError в Вас параметры запуска JVM, на всякий случай
  2. берут использование jmap на рабочей JVM ( jmap-histo < pid> ) при загрузке
  3. Analyize метрики (jmap-histo помещенный, или имеют jhat, смотрят на Ваш дамп "кучи"). Очень хорошо может случиться так, что Ваш из памяти прибывает из куда-нибудь неожиданного.

существуют, конечно, другие инструменты там, но jmap & jhat идут с Java 5 + 'из поля',

я полагал, что запись файла к локальному временному диску и затем порождению другого потока обрабатывает потоковую передачу так, чтобы поток сервлета кота мог быть снова использован. Это кажется, что было бы io тяжелый.

А-ч, я не думаю, что Вы не можете сделать этого. И даже если Вы могли, это звучать сомнительными. Поток кота, который управляет подключением, должен в управлении. Если Вы испытываете исчерпание ресурсов потока, тогда увеличивают число доступных потоков в ./conf/server.xml. Снова, метрики являются способом обнаружить, это - не просто предполагает.

Вопрос: Вы также работаете на EC2? Каковы параметры запуска JVM Вашего кота?

2
ответ дан Stu Thompson 11 September 2008 в 02:40
поделиться

Необходимо проверить две вещи:

  • Вы закрываете поток? Очень важный
  • , Возможно, Вы даете потоковые соединения "бесплатно". Поток не является большим, но много, много потоков одновременно могут украсть всю Вашу память. Создайте пул так, чтобы у Вас не могло быть определенного числа потоков, работающих одновременно
0
ответ дан Marcio Aguiar 11 September 2008 в 02:40
поделиться
  • 1
    интересный. и ПЕРЕМЕЩЕНИЕМ не является Действие. Action.values () просто имеет НЕЧТО и ПАНЕЛЬ – Ray Tayek 5 January 2012 в 02:00

toby является правильным, необходимо указывать прямо на S3, если Вы можете. Если Вы не можете, вопрос быть немного неопределенными для предоставления точного ответа: Насколько большой Ваша "куча" Java? Сколько потоков открыто одновременно, когда у Вас заканчивается память?
, Насколько большой Ваше чтение write/bufer (8K хорошо)?
Вы читаете 8K из потока, затем пишущий 8k к выводу, правильно? Вы не пытаетесь прочитать целое изображение из S3, буферизовать его в памяти, затем отправляя все это сразу?

при использовании буферов 8K у Вас могло бы быть 1 000 параллельных потоков, входящих ~8Megs пространства "кучи", таким образом, Вы определенно делаете что-то не так....

BTW, я не выбрал 8K из ничего, это - размер по умолчанию для буферов сокета, отправьте больше данных, скажите 1Meg, и Вы будете блокироваться на стопке tcp/ip, содержащей большой объем памяти.

1
ответ дан Tony BenBrahim 11 September 2008 в 02:40
поделиться

В дополнение к тому, что предложенный John, необходимо неоднократно сбрасывать поток вывода. В зависимости от Вашего веб-контейнера возможно, что это кэширует части или даже весь Ваш вывод и сбрасывает его сразу (например, для вычисления заголовка Довольной Длины). Это записало бы довольно мало памяти.

0
ответ дан Johannes Passing 11 September 2008 в 02:40
поделиться

Если вы можете структурировать свои файлы так, чтобы статические файлы были разделены и располагались в собственном сегменте, самая высокая производительность сегодня может быть достигнута с помощью Amazon S3 CDN, CloudFront .

0
ответ дан 26 November 2019 в 23:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: