Для простоты предположим, что мое приложение должно позволить тысячам пользователей видеть поток в режиме реального времени только для чтения в чате. Хост может печатать сообщения, но ни один другой пользователь не может - они просто видят, что набирают хосты, в режиме реального времени. Представьте, что пользователи следуют текстовой игре по спортивному событию.Как передавать данные во все экземпляры Google App Engine?
Каждый пользователь проверяет новые сообщения путем опроса один раз в секунду, используя простой вызов /get-recent-messages
на сервер GAE. (Прежде чем вы спросите, я считаю, что использование API каналов Google было бы слишком дорогостоящим.)
Учитывая, что это приложение используется многими тысячами пользователей одновременно, что означает, что работают десятки до сотен экземпляров GAE, как я могу получить эти /get-recent-messages
звонки, чтобы возвращать последние сообщения в чат-комнате с задержкой менее 1000 мс, минимизируя нагрузку на сервер и затраты на GAE?
Некоторые идеи, которые я имел:
- сообщения магазин чат в хранилище данных лиц.
- Очевидно, что это слишком медленно и дорого, особенно при использовании запросов/индексы
- магазин сообщения чата в Memcache ключей. Думаю, я бы использовал один ключ для хранения списка ключей для последних 50 сообщений, а затем еще 50 ключей, по одному для каждого сообщения.
- Это вызовет огромные узкие места, поскольку черепашка Memcache App Engine будет чередоваться по ключу, и, следовательно, все 500 экземпляров будут постоянно считывать из тех же ключей memcache и, таким образом, одного и того же сервера memcache.
- Хранить сообщения чата в памяти экземпляра, поддерживаемые memcache. И вытащите из memcache (как в # 2), когда память экземпляра устарела.
- Это может привести к дорогостоящему состоянию гонки, когда несколько запросов видят устаревший кеш памяти экземпляра и одновременно извлекают из memcache.
- Используйте фоновый поток для обновления памяти экземпляра из memcache. Это может выполняться один раз в секунду для каждого экземпляра, используя поток, запущенный в запросе на разминку. Он будет работать как # 3, но только с одним потоком, вместо случайных запросов, запускающих считывание memcache.
- Я не думаю, что это то, как фоновые потоки работают на App Engine. Я также не знаю, подходит ли это использование запросов на разминку.
- Использование Google's Pub/Sub service.
- Я понятия не имею, как это работает, и кажется, что это может быть излишним для этого прецедента.
- Запустите однократное задание cron, чтобы извлечь из memcache. Это было бы как # 4, за исключением того, что он не полагался на потоки фона.
- мне нужно это, чтобы работать на каждый экземпляр каждый второй. Я не верю, что API cron/taskqueue имеет способ запустить задание или задачу во всех активных экземплярах.
Мысли?
Если вы действительно попали в пределы, описанные в https://cloud.google.com/appengine/articles/best-practices-for-app-engine-memcache#distribute_load_across_the_keyspace, вы могли бы сделать что-то простое, как использование двух проектов движка приложений и балансировщик нагрузки. Я бы начал с стандартного подхода с хранилищем данных и memcache и посмотреть, как далеко это меня достает. – konqi
Моя первая мысль, когда я прочитал вопрос, был Cloud Pub/Sub, но я недостаточно осведомлен об этом, чтобы быть уверенным. Не зная больше о вашем приложении, я хотел бы сначала начать с datastore + memcache. Вы не говорите, как часто каждый чат будет публиковать новые сообщения, поэтому я не уверен, что хранилище данных будет «слишком медленным» (вы не говорите, если вам нужна сильная консистенция здесь). Вы можете использовать memcache как свой первый порт захода и агрегировать свои записи в хранилище данных, используя очередь для повышения устойчивости. – tx802
@konqi Меня не беспокоят ограничения. Просто беспокоился о стоимости. – Keith