Некоторые идеи:
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()