2

我想要做什麼(背景信息)? 我的任務是創建一個將表單數據發佈到另一個服務器的Google應用程序引擎應用程序(Python 2.7)。我嘗試連接的服務器的身份驗證使用用戶:密碼來交換cookie。通過將cookie與表單數據一起傳遞,我可以將數據發佈到服務器。我不擁有我要發佈的服務器,因此不能進行任何更改。每次您請求身份驗證Cookie時,都會使舊Cookie無效。所以我堅持cookie /會話,並在它到期時得到一個新的。Google App Engine由多個用戶共享的Python持久會話

問題我正在嘗試解決。 當用戶A提交表單數據時,Cookie仍然有效。 (大約需要45秒來處理所有表單數據) 用戶B正在提交表單數據,但現在Cookie無效。因此,通過爲用戶B申請一個新的Cookie,我們在用戶Cookie仍然處於處理狀態時使其無效。

那麼有沒有辦法鎖定/等待所有請求,直到會話完成刷新?或者這會是一個壞主意?

def get_session(self): 
    url= self.base_url + "/index.cfm" 
    form_fields = { 
     "email": "[email protected]", 
     "password": "passwerd", 
     "iStarAPI_fuseaction": "Login" 
    } 
    urlfetch.set_default_fetch_deadline(60) 
    #first we check the datastore if a persistent session exsists 
    persistent_s = PersistentSession.query(ancestor=ndb.Key(PersistentSession,'SESSION')).fetch() 
    #ok we found a session in the datastore if its not expired we are going to use that one 
    if persistent_s: 
     if persistent_s[0].expires_at > datetime.datetime.utcnow(): 
      return pickle.loads(persistent_s[0].session) 
     else: 
      try: 
       s = requests.Session() 
       s.post(url, data=form_fields) 
       date_now = datetime.datetime.utcnow() 
       delta = datetime.timedelta(seconds=1500) 
       session_expiry_time = date_now + delta 
       persistent_s[0].expires_at = session_expiry_time 
       persistent_s[0].session = pickle.dumps(s) 
       persistent_s[0].put() 
       return s 
      except Exception,e: 
       logging.error(e) 

    #there was no session in the datastore or it was expired we need a new one 
    else: 
     try: 
      s = requests.Session() 
      s.post(url, data=form_fields) 
      date_now = datetime.datetime.utcnow() 
      delta = datetime.timedelta(seconds=1500) 
      session_expiry_time = date_now + delta 
      persistent_s = PersistentSession(parent=ndb.Key(PersistentSession, 'SESSION')) 
      persistent_s.expires_at = session_expiry_time 
      persistent_s.session = pickle.dumps(s) 
      persistent_s.put() 
      #this is the important login session (all requests use the same session until it expires) 
      return s 
     except Exception, e: 
      logging.error(e) 

回答

0

A「鎖定」可以是「接近到期」標誌加上活性形式提交的計數器(遞增時提交的開始和何時結束遞減)。該標誌可以是到期時間的簡單檢查,但計數器需要在db中。

如果該標誌被設置,並且計數器非零,則阻止開始新的發佈(例如使用while循環)。在遞減計數器(從1到0)之前,只有最後一次有效發佈實際刷新了cookie。

但是,將「實時」請求鎖定時間過長可能會導致應用程序實例因超過時間配額而被殺害(例如,如果平均45秒偶爾會超過60)。

對此的一種可能的解決方案是將實際過帳推送到任務隊列中。如果發佈被鎖定,你只需要'失敗'所有的任務執行,並且GAE會自動重新嘗試它們(一段時間) - 一旦cookie被刷新並且鎖定被解除,任務應該自動地通過。缺點:由於任務失敗,這會在日誌中產生一些噪音。流量也非常高可能會導致超出任務隊列限制。

另一種可能性是在帖子臨近到期並且沒有其他帖子正在進行/等待時,在發佈帖子之後先發制人地刷新cookie。缺點:不能保證工作 - 如果請求流量高到在到期前沒有找到這樣的「空閒」點。

我認爲處理流量峯值期間處理鎖定的唯一可靠方法是使用數據存儲「緩衝」鎖定解除後您將重放的發佈作業(再次,任務隊列將是一種簡單的方法觸發重放操作)。