API - это интерфейс, через который вы получаете доступ к коду elses или через который чужой код обращается к вашим. По сути, это общедоступные методы и свойства.
Когда возможно, Вы не должны хранить все содержание файла, который будет подаваться в памяти. Вместо этого 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 общественности. Мое понимание техники:
Почему Вы только не указали бы на них на S3 url? Взятие артефакта от S3 и затем потоковая передача его через Ваш собственный сервер мне побеждают цель использовать S3, который должен разгрузить пропускную способность и обработку обслуживания изображений к Amazon.
Я соглашаюсь сильно и с toby и с John Vasileff - S3 является большим для от загрузки больших мультимедийных объектов, если можно терпеть связанные проблемы. (Экземпляр собственного приложения делает это для 10-1000MB FLVs и MP4s.), Например: Никакие частичные запросы (заголовок диапазона байта), все же. Нужно обработать это 'вручную', случайное время простоя, и т.д.
, Если это не опция, код John выглядит хорошим. Я нашел, что буфер байта 2k FILEBUFFERSIZE является самым эффективным в метках микроместа размещения. Другой опцией мог бы быть общий FileChannel. (FileChannels ориентированы на многопотоковое исполнение.)
Однако я также добавил бы, что предположение, что вызвало из ошибки памяти, является классической ошибкой оптимизации. Вы улучшили бы свои шансы на успех путем работы с твердыми метриками.
существуют, конечно, другие инструменты там, но jmap & jhat идут с Java 5 + 'из поля',
я полагал, что запись файла к локальному временному диску и затем порождению другого потока обрабатывает потоковую передачу так, чтобы поток сервлета кота мог быть снова использован. Это кажется, что было бы io тяжелый.
А-ч, я не думаю, что Вы не можете сделать этого. И даже если Вы могли, это звучать сомнительными. Поток кота, который управляет подключением, должен в управлении. Если Вы испытываете исчерпание ресурсов потока, тогда увеличивают число доступных потоков в ./conf/server.xml. Снова, метрики являются способом обнаружить, это - не просто предполагает.
Вопрос: Вы также работаете на EC2? Каковы параметры запуска JVM Вашего кота?
Необходимо проверить две вещи:
toby является правильным, необходимо указывать прямо на S3, если Вы можете. Если Вы не можете, вопрос быть немного неопределенными для предоставления точного ответа: Насколько большой Ваша "куча" Java? Сколько потоков открыто одновременно, когда у Вас заканчивается память?
, Насколько большой Ваше чтение write/bufer (8K хорошо)?
Вы читаете 8K из потока, затем пишущий 8k к выводу, правильно? Вы не пытаетесь прочитать целое изображение из S3, буферизовать его в памяти, затем отправляя все это сразу?
при использовании буферов 8K у Вас могло бы быть 1 000 параллельных потоков, входящих ~8Megs пространства "кучи", таким образом, Вы определенно делаете что-то не так....
BTW, я не выбрал 8K из ничего, это - размер по умолчанию для буферов сокета, отправьте больше данных, скажите 1Meg, и Вы будете блокироваться на стопке tcp/ip, содержащей большой объем памяти.
В дополнение к тому, что предложенный John, необходимо неоднократно сбрасывать поток вывода. В зависимости от Вашего веб-контейнера возможно, что это кэширует части или даже весь Ваш вывод и сбрасывает его сразу (например, для вычисления заголовка Довольной Длины). Это записало бы довольно мало памяти.
Если вы можете структурировать свои файлы так, чтобы статические файлы были разделены и располагались в собственном сегменте, самая высокая производительность сегодня может быть достигнута с помощью Amazon S3 CDN, CloudFront .