GAE Имея задачи генерировать страницы для пользователя - PullRequest
1 голос
/ 18 мая 2010

У меня есть веб-приложение, которое я хотел бы иметь следующие функции:

  1. пользователь дает URL
  2. webapp получает данные json с этого URL и другие с одного сайта (это может занять от 1 до 10 секунд)
  3. веб-приложение использует данные для создания страницы для пользователя

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

Кажется, что API Google Tasks был бы полезен для этого, но я не понимаю, как я могу выполнить задачу, а затем использовать выходные данные задачи для генерации страницы (как основное приложение узнает, когда задание было выполнено?)

Как лучше всего решить эту проблему?

Заранее спасибо

1 Ответ

3 голосов
/ 18 мая 2010

Некоторые идеи:

1) Механизм приложения может одновременно обслуживать более одного запроса. Попробуйте - движок приложения, вероятно, раскрутит более одного экземпляра вашего приложения => можно выполнить несколько запросов одновременно. Хотя с таким большим временем запроса, я не ожидал бы, что оно будет сильно масштабироваться (они рекомендуют время запроса / ответа менее чем за 1 секунду - см. Эту ссылку ).

2) Если вы хотите быстро вернуться к пользователю, вы можете поставить в очередь задачи, как вы предложили. Затем попросите веб-страницу пользователя (возможно, через метатег http-эквивалент или JavaScript) опрашивать сервер каждые пару секунд, чтобы узнать, готова ли страница.

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

Вот очень простой пример того, как вы могли бы сделать это:

import hashlib

from google.appengine.api.labs import taskqueue
from google.appengine.ext import db, webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class BuiltPage(db.Model):
    html = db.TextProperty()

class PageBuilder(webapp.RequestHandler):
    """Handler called by the task queue to build the page."""
    def post(self):
        key = self.request.get('key')
        url = self.request.get('url')
        import time
        time.sleep(5) # pretend it takes a while to build the page
        html = "you asked for %s" % url # do real stuff to build the page here ...
        BuiltPage(key_name=key, html=html).put() # should check for errors ...

def html_to_redir_to_built_page(hexkey):
    "Page to show while we wait.  Auto-refreshes until we get the built page."""
    new_url = '/get_built_page?k=' + hexkey
    refresh_tag = '<meta http-equiv="refresh" content="2;%s"/>' % new_url
    return '<html><head>%s</head><body>please wait</body></html>' % refresh_tag

class BuildPageForURL(webapp.RequestHandler):
    """Handles requests by a user to build the page for the request URL."""
    def get(self):
        url = self.request.get('url')
        key = hashlib.md5(url).hexdigest()
        # optimization: check datastore to see if it was already generated?
        taskqueue.add(url='/buildit', params=dict(key=key, url=url))
        self.redirect('/get_built_page?k=' + key)

class GetBuiltPage(webapp.RequestHandler):
    """Returns the built page if it is ready, otherwise returns a page which will retry later"""
    def get(self):
        key = self.request.get('k')
        bp = BuiltPage.get_by_key_name(key)
        if bp:
            self.response.out.write(bp.html)
            # maybe cleanup if you know this is a 1-time request: bp.delete()
        else:
            self.response.out.write(html_to_redir_to_built_page(key))

application = webapp.WSGIApplication([('/',               BuildPageForURL),
                                      ('/buildit',        PageBuilder),
                                      ('/get_built_page', GetBuiltPage)])
def main(): run_wsgi_app(application)
if __name__ == '__main__': main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...