一些想法:
1)應用引擎可以用於在同一時間超過一個請求。嘗試一下 - 應用程序引擎可能會啓動不止一個應用程序實例=>多個請求可以一次完成。儘管請求時間很長,但我不希望它有很大的擴展(他們建議在1秒內請求/響應時間 - see this link)。
2)如果您想快速返回給用戶,可以按照您的建議排入任務隊列。然後讓用戶的網頁(通過元標記http-equiv或JavaScript)每隔幾秒輪詢一次服務器以查看頁面是否準備就緒。 3)如果生成的頁面可能需要再次使用,則應考慮對其進行memcaching以嘗試節省再次生成它的工作量。加載時間爲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()
非常感謝你的非常詳細的解答。我唯一的問題是'GetBuiltPage'中的'BuiltPage.get_by_key_name'調用將會很昂貴,但我想這是無法避免的。 我一直在想,只需在JS中編寫應用程序,並讓用戶自己下載文件,但不會有任何緩存。我希望有一天左右的內容緩存,儘管沒有必要。 再次感謝! – mellort 2010-05-18 03:38:19