2010-03-04 4 views
5

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

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

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

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

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

+0

Ну, консенсус, похоже, заключается в том, что стандартный способ - сделать то, что я предложил для опции c. Тем не менее, я считаю, что должен быть лучший способ - меня беспокоит неловкость временных файлов - им нужно открыть дополнительные порты erlang (более одного раза, если я планирую прочитать файл в какой-то момент) и они делят между двумя или более процессами то, что я хотел бы обработать одним. Это, однако, то, что я планировал сделать - я бы предпочел, чтобы кто-то мог делать что-то по-другому. – Aoriste

+0

Вам необходимо сохранить данные. Практически это делается в памяти или на запоминающем устройстве. Ваш вопрос говорит, что память не вариант; ваш комментарий говорит, что вам не нравится хранить его на устройстве. Единственным оставшимся вариантом является оккультизм ... – Zed

ответ

2

На мой взгляд, вариант b явно превосходит один.

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

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

+0

Я тайно искал оправдания для б, спасибо за помощь в его обеспечении. От меня это имеет смысл из обслуживания кода, но этого было недостаточно для меня, чтобы реализовать его. – Aoriste

0

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

0

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