2010-05-17 35 views
1

頁我有一個Web應用程序,我想有以下功能:GAE有任務生成用戶

  1. 用戶給出了一個網址
  2. web應用從同一網站會從該URL JSON數據及其他(這可以從1-10秒任何地方)
  3. web應用程序使用的數據爲用戶

利用這種方法生成頁面,我相信,如果服務器在獲取數據的一個用戶的過程中,然後th其他用戶將無法加載該頁面(服務器繁忙)。如果可能,我想避免這種情況。

似乎Google Tasks API對此很有用,但我看不到我如何運行該任務,然後使用任務的輸出生成頁面(主應用程序如何知道何時任務完成了?)

解決此問題的最佳方法是什麼?

在此先感謝

回答

3

一些想法:

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() 
+0

非常感謝你的非常詳細的解答。我唯一的問題是'GetBuiltPage'中的'BuiltPage.get_by_key_name'調用將會很昂貴,但我想這是無法避免的。 我一直在想,只需在JS中編寫應用程序,並讓用戶自己下載文件,但不會有任何緩存。我希望有一天左右的內容緩存,儘管沒有必要。 再次感謝! – mellort 2010-05-18 03:38:19