Легкая техника уведомления - PullRequest
12 голосов
/ 18 сентября 2011

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

Псевдокод:

def recent_activity_post_save():
    notify_view()

[in the view]
while not new_activity():
    sleep(1)
return HttpResponse(new_activity())

Первое, что приходит в голову, это запросы к БД каждую секунду.Не осуществимоДругие варианты:

  1. с использованием кэша в качестве службы уведомлений
  2. с использованием специального инструмента, такого как Celery (я бы предпочел этого не делать, потому что это выглядит как перебор)

Какой лучший путь сюда?

Ответы [ 8 ]

5 голосов
/ 02 октября 2011

Я бы посоветовал сделать это проще ...

Создайте таблицу базы данных для хранения ваших событий, вставьте в эту таблицу при необходимости, а затем просто внедрите простой метод опроса ajax, чтобы подключаться к серверу каждые x секунд на стороне клиента.

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

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

Ваше представление будет просто как любое другое представление, вытягивая верхние x строки из этой таблицы RecentActivity (необязательно на основе параметров запроса и т. Д.).

Тогда на стороне клиента у вас будет простой ajax-опрашиватель, который будет отображать ваш взгляд каждые x секунд. Нет недостатка в сложных плагинах и технологиях, которые вы можете использовать, но написание собственных не так уж и сложно:

function simplePoll() {
  $.get("your-url", {query-parameters}, function(data){
    //do stuff with the data, replacing a div or updating json or whatever
    setTimeout(simplePoll, delay);
  });
}

Мое мнение таково, что проблемы с производительностью на самом деле не являются проблемами, пока ваш сайт не станет достаточно успешным, чтобы они стали проблемой. Традиционная реляционная база данных может масштабироваться довольно хорошо, пока вы не достигнете уровня успеха, такого как Twitter, Google и т. Д. Большинство из нас не на этом уровне:)

2 голосов
/ 28 сентября 2011

Рассматривали ли вы использование сигналов?Вы можете отправить сигнал в Recent_activity_post_save (), и может быть слушатель, который хранит информацию в кеше.

Представление просто ссылается на кэш, чтобы увидеть, есть ли новые уведомления.Конечно, вам не нужны сигналы, но имхо это будет немного чище, так как вы можете добавить больше «обработчиков уведомлений».

Это кажется оптимальным, потому что вам не нужно опрашивать БД (искусственная загрузка), уведомления «видны» практически сразу (только после времени, необходимого для обработки сигналов и взаимодействия с кешем).

Таким образом, псевдокод будет выглядеть так:

# model
def recent_activity_post_save():
    post_save_signal.send()

# listener
def my_handler( ... ):
    cache.set( 'notification', .... )

post_save_signal.connect( my_handler )

# view
def my_view( request ):
    new_notification = None
    while not new_notification:
        sleep(1)
        new_notification = cache.get( 'notification' )
    return HttpResponse(...)
1 голос
/ 18 сентября 2011

Вы можете использовать кометное решение, например Ape project .Этот вид проекта предназначен для отправки данных в реальном времени в браузер и может использовать функцию современных веб-сокетов в браузерах.

0 голосов
/ 02 октября 2011

Я не вижу необходимости ограничивать себя использованием длинных опросов, если в этом нет особой необходимости.Существуют библиотеки, написанные для использования наилучшего возможного варианта (может быть короткий опрос, длинный опрос, веб-сокеты или даже крошечный флэш-плагин, если ни один из предыдущих вариантов не доступен).В Node.js есть одна из лучших библиотек для такой работы, которая называется Socket.IO, но, к счастью, есть также две реализации Python: gevent-socketio и tornadio , нопозже он построен поверх фреймворка торнадо, так что, возможно, об этом не может быть и речи.

Если это вас устраивает, вы можете объединить их с некоторыми базами данных NoSQL (документ), которые оказались намного быстрее и легче, чем реляционные.базы данных.Существует много вариантов, в том числе CouchDB, MongoDB, Redis, ... Сочетание Socket.IO и БД на основе документов оказалось быстрым, легким и надежным.

Хотя я видел вас 'Мы уже рассматривали NoSQL в комментариях, мое личное мнение таково: если вам нужно быстрое и простое решение и варианты, которые вам подходят, это лучший шанс, который вы можете использовать.

0 голосов
/ 01 октября 2011

Вы должны решить, предпочитаете ли вы использовать «вытягивающую» или «проталкивающую» архитектуру для доставки ваших сообщений, см. Этот пост на quora ! Если вы предпочитаете решение, которое «отправляет» уведомления своим получателям, системы на основе кэширования / nosql предпочтительны, поскольку они не создают такой высокой нагрузки для большого количества операций записи.

Redis, например, со своими отсортированными структурами данных set / list предлагает вам множество примеров. См. Например этот пост (хотя это и не Python), чтобы получить представление. Вы также можете посмотреть «реальные» очереди сообщений, например RabbitMQ !

Для клиентского соединения другие посты здесь уже должны были дать вам некоторые идеи о том, как использовать витые и подобные фреймворки.

А Сельдерей всегда может быть хорошим инструментом, например. Иметь всю запись в потоки активности пользователей в асинхронном задании!

0 голосов
/ 27 сентября 2011

Вот аналогичное обсуждение, отвечающее со стороны сервера: Выполнение ходов с websockets и python / django (/ twisted?) самый важный ответ - этот .

Также есть этот ответ , указывающий на очень солидную альтернативу попыткам сделать это со стороны Джанго.

Если вы действительно хотите, чтобы это служило в существующем приложении Django, не делайте этого на стороне сервера. Удержание этого сокета HTTP в качестве соединения с одним браузером - это быстрый способ взломать ваше приложение. Есть две разумные альтернативы: изучить различные варианты веб-сокетов (например, тот, что использует Pyramid для размещения службы) или посмотреть, как браузер периодически отправляет запрос опроса на сервер в поисках обновлений.

0 голосов
/ 27 сентября 2011

Если вы ищете решение комета , тогда вы можете использовать orbited. Позвольте мне предупредить вас, что, поскольку это довольно нишевое решение, очень сложно найти хорошую документацию по развертыванию и использованию orbited в производственных средах.

0 голосов
/ 18 сентября 2011

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

...