2010-03-04 13 views
5

Entonces, digamos que estoy escribiendo un servidor web y quiero admitir archivos "muy grandes". Supongamos además que quiero hacer esto a través del tipo MIME estándar multipart/form-data. Debo decir que estoy usando erlang y que planeo recolectar paquetes http a medida que se devuelven desde erlang:decode_packet/2, pero no quiero recopilar realmente el cuerpo de la solicitud hasta que el manejador de solicitudes http encuentre el lugar para que cargue el contenido cargado. ¿Debo I¿Cómo manejo cargas de archivos muy grandes en un servidor web Erlang?

a) seguir adelante y recoger el cuerpo de todos modos, ignorando la posibilidad de que sea muy grande y, por lo tanto, posiblemente se cuelgue el servidor debido a que se está quedando sin memoria?

b) abstenerse de recibir en el socket cualquier cuerpo de solicitud (posiblemente inexistente) hasta que se hayan procesado los encabezados?

c) ¿hacer algo más?

Un ejemplo para la respuesta c podría ser: engendrar otro proceso para recopilar y escribir el contenido cargado en una ubicación temporal (para minimizar el uso de memoria), al mismo tiempo dar esa ubicación al controlador de solicitud http para su posterior procesamiento. Pero simplemente no lo sé, ¿hay una técnica estándar aquí?

+0

Bueno, el consenso parece ser que la forma estándar es hacer lo que sugerí para la opción c. Aún así, creo que debe haber una manera mejor, me molesta la torpeza de los archivos temporales, requieren que se abran puertos de erlang adicionales (más de una vez si planeo leer el archivo de nuevo en algún momento), y dividen entre dos o más procesos lo que me gustaría que manejara uno. Esto es, sin embargo, lo que había estado planeando hacer: había pensado que alguien podría estar haciendo las cosas de otra manera. – Aoriste

+0

Necesita almacenar los datos. Prácticamente esto se hace en la memoria o en un dispositivo de almacenamiento. Su pregunta dice que la memoria no es una opción; tu comentario dice que tampoco te gusta almacenarlo en un dispositivo. La única opción restante es el ocultismo ... – Zed

Respuesta

2

En mi opinión, la opción b es claramente la superior.

Durante el período de tiempo que no está leyendo el socket, el código TCP continuará almacenando los datos entrantes dentro del kernel. A medida que lo hace, anunciará un tamaño de ventana TCP más pequeño y más pequeño para el servidor HTTP, hasta que finalmente (cuando los búferes de recepción TCP en el kernel estén llenos), la ventana de TCP se cerrará.

En otras palabras, al no leer el socket, está permitiendo que TCP-control de flujo haga su trabajo.

+0

Estaba buscando secretamente la justificación para hacer b, gracias por ayudarme a proporcionarlo. De mí, tiene más sentido desde el mantenimiento del código, pero esto no fue suficiente para implementarlo. – Aoriste

0

En mi implementación, utilizo el ejemplo para la respuesta c - leo desde el fragmento de socket por fragmento y almaceno los fragmentos en el archivo temporal. Además, afaik yaws utiliza la técnica de simillar; puede verlo en yaws/src/yaws_multipart.erl

0

Almacenar en un archivo temporal también es la forma en que PHP hace las cosas, por lo que es una forma probada y probada. Podría contar los bytes recibidos y desconectarse si alcanza un tamaño que no tiene sentido.

Cuestiones relacionadas