2016-12-01 2 views
0

Я работаю над флеш-приложением, которое будет обрабатывать большие загрузки файлов (250 МБ +). Я запускаю это приложение, используя Tornado с несколькими процессами, поэтому он может обрабатывать параллельные запросы без блокировки.MemoryError при загрузке больших файлов на HTTP-сервер Tornado

import os.path 
import tempfile 
from flask import Flask, request, jsonify 
from tornado.wsgi import WSGIContainer 
from tornado.httpserver import HTTPServer 
from tornado.ioloop import IOLoop 
from werkzeug import secure_filename 

app = Flask(__name__) 

@app.route("/test", methods=["GET"]) 
def test_route(): 

    return jsonify(msg='Ok'), 200 

@app.route("/upload", methods=["GET", "POST"]) 
def upload_file(): 

    if request.method == 'POST': 
     temp_directory = app.config['TMP_DIRECTORY'] 
     uploaded_file = request.files['filename'] 
     filename = secure_filename(uploaded_file.filename) 
     uploaded_file.save(os.path.join(temp_directory, filename)) 
     return jsonify(msg="File upload successfully"), 200 

    else: 
     return jsonify(msg="Use POST to upload a file"), 200 


if __name__ == '__main__': 
    app.config['TMP_DIRECTORY'] = tempfile.mkdtemp() 
    address = '0.0.0.0' 
    port = 8000 

    max_buffer_size = 500 * 1024 * 1024 
    server = HTTPServer(WSGIContainer(app), max_buffer_size=max_buffer_size) 
    server.bind(port=port, address=address) 

    print("Starting Tornado server on %s:%s" % (address, port)) 
    server.start(2) 
    IOLoop.instance().start() 

Я получаю следующее MemoryError при загрузке нескольких больших файлов одновременно:

$ curl -i -F name=file -F [email protected] http://127.0.0.1:8000/upload 

ERROR:tornado.application:Uncaught exception 
Traceback (most recent call last): 
    File "/usr/lib64/python2.7/site-packages/tornado/http1connection.py", line 238, in _read_message 
    delegate.finish() 
    File "/usr/lib64/python2.7/site-packages/tornado/httpserver.py", line 285, in finish 
    self.request.body = b''.join(self._chunks) 
MemoryError 

Я считаю, что Торнадо хранит весь загруженный файл в память и только записывает его на диск после того, как клиент завершена загрузка. Можно ли изменить это поведение, чтобы выписать куски на диск?

ответ

1

Вы не понимаете, как работает Торнадо. Это не волшебным образом делает ваше приложение Flask «способным обрабатывать одновременные запросы без блокировки» - использование Flask в Tornado's WSGIContainer равно less масштабируемое, чем использование флажка на чем-то вроде uwsgi или gunicorn. См. warning in WSGIContainer's documentation.

Если вы делали это как родное приложение Tornado (без Flask), то вы могли бы использовать декоратор tornado.web.stream_request_body для обработки больших загрузок без буферизации всего объекта в памяти.

+0

Вы совершенно правы. Вместо этого я собираюсь использовать пушки. –

 Смежные вопросы

  • Нет связанных вопросов^_^