Веб-сайты и темы Tornado

Я новичок в Tornado и Python Threads. То, что я хотел бы достичь, следующее: У меня есть веб-сервер Tornado, который принимает запросы от пользователей. Я хочу хранить некоторые данные локально и периодически записывать их в базу данных в виде массивов.

import tornado.ioloop
import tornado.web
import threading

# Keep userData locally in memory
UserData = {}

def background(f):
    """
    a threading decorator
    use @background above the function you want to thread
    (run in the background)
    """
    def bg_f(*a, **kw):
        threading.Thread(target=f, args=a, kwargs=kw).start()
    return bg_f

@background
def PostRecentDataToDBThread(iter = -1):
    i = 0
    while iter == -1 or i < iter: 
        #send data to DB
        UserData = {}
        time.sleep(5*60)
        i = i + 1

class AddHandler(tornado.web.RequestHandler):
    def post(self):
        userID = self.get_argument('ui')
        Data = self.get_argument('data')

        UserData[userID] = Data 


if __name__ == "__main__":
    tornado.options.parse_command_line()

    print("start PostRecentDataToDBThread")
    ### Here we start a thread that periodically sends data to the data base.
    ### The thread is called every 5min. 
    PostRecentDataToDBThread(-1)

    print("Started tornado on port: %d" % options.port)

    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/add", AddHandler)
    ])
    application.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

Это хороший способ достичь моей цели? Я хотел бы минимизировать время блокировки сервера. Или я должен использовать gevent или что-нибудь еще? Могу ли я столкнуться с проблемами, обратившись к UserData как из Tornado, так и из потока? Консистенция данных здесь не так важна, пока нет сбоя сервера.

Ответ 1

Tornado не предназначен для многопоточности. Он основан на epoll для переключения контекста между различными частями кода.

В целом я бы рекомендовал отправить данные для разделения рабочего процесса через очередь сообщений (например, pika + RabbitMQ, он очень хорошо интегрируется с Tornado). Рабочий процесс может накапливать сообщения с данными и записывать их в базу данных в пакетном режиме, или вы можете реализовать любую другую логику обработки данных с помощью этой настройки.

В качестве альтернативы вы можете использовать, например, Redis с brukva, чтобы просто асинхронно записывать входящие данные в базу данных в памяти, что, в свою очередь, будет асинхронно выгружать ее диск в зависимости от конфигурации Redis.