Python Tornado - сделать сообщение до возврата сразу, пока Async Function продолжает работать

StackOverflow https://stackoverflow.com/questions/3869421

  •  28-09-2019
  •  | 
  •  

Вопрос

поэтому у меня есть обработчик ниже:

class PublishHandler(BaseHandler):

    def post(self):
        message = self.get_argument("message")
        some_function(message)
        self.write("success")

Проблема, которую я сталкиваюсь с тем, что uvere_function () требует некоторого времени для выполнения, и я хотел бы, чтобы пост запрос вернуться сразу, когда они называются и для некоторой функции (), которые могут быть выполнены в другом потоке / процессе, если это возможно.

Я использую Беркли БД в качестве базы данных и то, что я пытаюсь сделать, это относительно просто.

У меня есть база данных пользователей каждый с фильтром. Если фильтр соответствует сообщению, сервер отправит сообщение пользователю. В настоящее время я тестирую с тысячами пользователей и, следовательно, при каждой публикации сообщения через почтовый запрос, он итализатор по тысячам пользователей, чтобы найти совпадение. Это моя наивная реализация делать вещи и, отсюда моим вопросом. Как мне сделать это лучше?

Это было полезно?

Решение

Вы можете сделать это, используя свой IOLoopС. add_callback метод так:

loop.add_callback(lambda: some_function(message))

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

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

Более надежное решение - это запустить его в отдельном потоке или процессе. То Лучший Способ с Python - это использовать процесс из-за GIл (я настоятельно рекомендую читать на том, если вы не знакомы с ним). Однако на однопроцессорной машине резьбовая реализация будет работать так же хорошо, и может быть проще реализовать.

Если вы собираетесь порезной маршрут, вы можете построить хороший модуль «Async Expertor» с Mutex, нитью и очередью. Проверьте multiprocessing Модуль, если вы хотите пойти на маршрут, используя отдельный процесс.

Другие советы

Я пробовал это, и я считаю, что запрос не завершается до вызванного обратных вызовов.

Я думаю, что грязный взлом будет называть два уровня ADD_Callback, например:

  def get(self):
    ...
    def _defered():
      ioloop.add_callback(<whatever you want>)
    ioloop.add_callback(_defered)
    ...

Но это в лучшем случае хаки. Я ищу лучшее решение прямо сейчас, наверное, в конечном итоге с некоторыми очередью сообщений или простой раствором потока.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top