Как справиться с очень большими загрузками файлов на веб-сервере Erlang?

Итак, допустим, я пишу веб-сервер и хочу поддерживать загрузку «очень больших» файлов. Далее предположим, что я намереваюсь сделать это с помощью стандартного типа MIME multipart/form-data. Я должен сказать, что я использую erlang и планирую собирать http-пакеты по мере их возврата из erlang:decode_packet/2, но я не хочу фактически собирать тело запроса, пока обработчик http-запроса не найдет место для загруженного контента. Нужно ли мне

а) все равно собрать тело, игнорируя возможность того, что оно будет очень-очень большим и, следовательно, может привести к сбою сервера из-за нехватки памяти?

б) воздерживаться от получения на сокете любого (возможно, несуществующего) тела запроса до тех пор, пока заголовки не будут обработаны?

в) сделать что-то еще?

Примером ответа c может быть: создать другой процесс для сбора и записи загруженного контента во временное расположение (чтобы свести к минимуму использование памяти), одновременно предоставляя это место обработчику http-запросов для дальнейшей обработки. Вот только не знаю - есть ли здесь стандартная методика?


person Aoriste    schedule 04.03.2010    source источник
comment
Ну, консенсус, кажется, заключается в том, что стандартный способ - сделать то, что я предложил для варианта c. Тем не менее, я чувствую, что должен быть лучший способ - меня беспокоит неуклюжесть временных файлов - они требуют открытия дополнительных портов erlang (более одного раза, если я планирую снова прочитать файл в какой-то момент), и они делят между двумя или более процессами то, что я хотел бы обрабатывать одним. Это, однако, то, что я планировал сделать - я надеялся, что кто-то может делать что-то по-другому.   -  person Aoriste    schedule 05.03.2010
comment
Вам нужно сохранить данные. Практически это делается в памяти или на запоминающем устройстве. В вашем вопросе говорится, что память не подходит; в вашем комментарии говорится, что вам тоже не нравится хранить его на устройстве. Единственный оставшийся вариант - оккультизм...   -  person Zed    schedule 05.03.2010


Ответы (3)


На мой взгляд, вариант б явно лучше.

В течение периода времени, когда вы не читаете сокет, код TCP будет продолжать буферизировать входящие данные внутри ядра. При этом он будет сообщать HTTP-серверу все меньший и меньший размер окна TCP, пока в конце концов (когда приемные буферы TCP в ядре будут заполнены) окно TCP не закроется.

Другими словами, не читая сокет, вы позволяете управлению потоком TCP выполнять свою работу.

person Bruno Rijsman    schedule 06.03.2010
comment
Я тайно искал оправдание для того, чтобы сделать b, спасибо, что помогли предоставить его. Для меня это имеет смысл от обслуживания кода, но мне этого было недостаточно для его реализации. - person Aoriste; 07.03.2010

В моей реализации я использую ваш пример для ответа c - я читаю из сокета фрагмент за фрагментом и сохраняю фрагменты во временный файл. Кроме того, afaik yaws использует аналогичную технику - вы можете увидеть ее в yaws/src/yaws_multipart.erl.

person W55tKQbuRu28Q4xv    schedule 04.03.2010

Сохранение во временном файле — это тоже способ, которым работает PHP, так что это проверенный способ. Вы можете подсчитать полученные байты и отключиться, если они достигнут размера, который не имеет смысла.

person Tor Valamo    schedule 04.03.2010