Форум сайта python.su
0
Здравствуйте. Делаю приложение на торнадо. Написал тестовый обработчик
class AdminHandler(BaseHandler): @tornado.web.authenticated @tornado.web.asynchronous @gen.engine def get(self): response = yield gen.Task(self.acync_func_test, 'my') print response self.render('admin/index.html') def acync_func_test(self, argument, callback): for i in xrange(1,59999000): i**2+2-12 callback(argument)
Отредактировано alekseyxxxx (Авг. 30, 2013 09:38:21)
Офлайн
Я не знаю устройства торнады, могу лишь сказать, что если у вас в асинхронной системе выполняется какой-то код и в нём нету никаких точек прерывания, типа того же yield, то этот код будет выполняться без прерываний, весь. Никаких чудес не будет, если функция async_func_test что-то делает долго, то в этом время все будут ждать её. Видимо, в функции надо генерить с помощью yield точки прерывания, наверное так и сделано в торнаде, я не знаю, как ещё по другому можно реализовать такой фунционал в python
Офлайн
32
alekseyxxxxОна и вызывается асинхронно, суть в том что она блокирующая, вам нужно использовать неблокирующие ф-ии.
Как вызвать функцию асинхронно?
Офлайн
0
Ну вроде стало понятно.
o7412369815963Над этим тоже думал. На хабре есть пример, когда на каждый запрос создаются потоки. http://habrahabr.ru/post/116892/
Либо запустить ф-ию в другом потоке, но это плохой путь.
class ThreadableMixin: def start_worker(self): threading.Thread(target=self.worker).start() def worker(self): try: self._worker() except tornado.web.HTTPError, e: self.set_status(e.status_code) except: logging.error("_worker problem", exc_info=True) self.set_status(500) tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results)) def results(self): if self.get_status()!=200: self.send_error(self.get_status()) return if hasattr(self, 'res'): self.finish(self.res) return if hasattr(self, 'redir'): self.redirect(self.redir) return self.send_error(500)
class Handler(tornado.web.RequestHandler, ThreadableMixin): def _worker(self): self.res = self.render_string("template.html", title = _("Title"), data = self.application.db.query("select ... where object_id=%s", self.object_id) ) @tornado.web.asynchronous def get(self, object_id): self.object_id = object_id self.start_worker(
Отредактировано alekseyxxxx (Сен. 1, 2013 08:51:55)
Офлайн
32
alekseyxxxxИз за GIL питон код будет работать только в одном потоке, т.е. если вы блокируете питон-кодом for in xrange то другие потоки не работают, если вы заблокируете не питон-кодом (io операции, обычно ими блокируют, db.query, urllib.urlopen, time.sleep …) то другой питон-код в других потоках будет работать.
Получается, что хоть клиенты и не блокируются, но ждут ответа дольше. Или я не так понимаю?)
Офлайн
0
Просто в разработке есть приложение на tornado на websocket. Все общение идет только через вебсокеты. И интересно сколько способен выдержать tornado. Как я понял, если не писать ‘асинхронным стилем’, то клиенты будут блокироваться. Ну, например, самая простая функция:
def on_message(self, msg): user_id = msg['id'] user = db.query(User).get(id)
Отредактировано alekseyxxxx (Сен. 1, 2013 13:09:43)
Офлайн
32
alekseyxxxxДа, для mongodb можете попробовать asyncmongo, не поддерживает весь функционал, но для 99% случаев достаточно. Он асинхронный - не будет блокировать.
И получается, что к примеру 2000 клиентов одновременно отправят запрос, то обработка будет последовательная.
alekseyxxxxЕсли процесс торнадо не будет справляться, то можно запустить их несколько экземпляров (форкнуть), и балансировщиком раскидать нагрузку (пример конфига nginx), таким же образом можно задействовать несколько серверов с кучей процессов торнадо, если нагрузка большая.
И интересно сколько способен выдержать tornado
Офлайн
32
alekseyxxxxНе знаю, я бы сначала сформулировал задачу, предполагаемые нагрузки, придумал бы несколько вариантов архитектуры, выложил на форуме для обсасывания, потом сделал бы прототип, потом если было б время, сделал бы нагрузочное тестирование.
Не подскажите, может есть полезные ссылки и ресурсы на которых можно поподробнее почитать.
Офлайн
0
Ну сейчас на данный момент так и сделано. Т.е. нжинкс балансирует нагрузку на несколько инстансов торнадо. А клиенты с разных инстансов общаются через редис. Вариант с монго привел для примера) Основная база postgres, ну для него тоже есть асинхроная библиотека. Попробую реализовать через нее, и провести нагрузочное тестирование) Спасибо за пояснения)
Офлайн
15
Не подскажете на эту же тему каким образом лучше реализовать такое. Пользователь заходит на сайт, нажимает кнопочку, запускается действие(настройка свитча по snmp, например), длится оно около минуты и лог этого действия realtime отображается у пользователя. Начал делать через торнадо и вебсокеты, но наткнулся на тоже самое - два пользователя одновременно не могут запустить эту настройку. Как мне сейчас лучше поступить?
Офлайн