Подтвердить что ты не робот

Легкая технология уведомления

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

псевдокод:

def recent_activity_post_save():
    notify_view()

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

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

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

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

4b9b3361

Ответ 1

Я бы предложил сохранить это просто...

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

У меня есть проблемы с другими решениями, учитывая использование push-уведомления или использование хранилища данных noSql. Это намного сложнее, чем традиционная система pull-notification, использующая инструменты, встроенные в среду 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

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

Вид будет просто ссылаться на кеш, чтобы увидеть, есть ли новые уведомления. Конечно, вам не нужны сигналы, но IMHO было бы немного чище, так как вы могли бы добавить больше "обработчиков уведомлений".

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

Итак, псевдокод будет выглядеть так:

# 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(...)

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

Здесь аналогичное обсуждение, отвечающее с точки зрения сервера: Создание перемещений w/websockets и python/django (/twisted?) , самый важный ответ - этот.

Здесь также этот ответ, указывая на очень прочную альтернативу попыткам этого из Django.

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

Ответ 7

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

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

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

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

Ответ 8

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

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

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