多个用户共享的Google App Engine Python持久会话

时间:2015-04-28 13:55:30

标签: python-2.7 google-app-engine session-cookies python-requests

我想做什么(背景信息)? 我的任务是创建一个谷歌应用程序引擎应用程序(Python 2.7),将表单数据发布到另一台服务器。我尝试连接的服务器的身份验证使用user:password来换取cookie。我可以通过传递cookie和表单数据将数据发布到服务器。我没有自己发布的服务器,因此无法进行任何更改。每次请求身份验证cookie时,它都会使旧cookie无效。所以我坚持cookie /会话,当它到期时获得一个新的。

问题我想解决。 当用户A提交表单数据时,cookie仍然有效。 (大约需要45秒来处理所有表单数据) 用户B正在提交表单数据,但现在cookie无效。因此,通过为用户B请求新的cookie,我在其数据仍在处理时使用户A cookie无效。

那么有没有办法锁定/等待所有请求,直到会话完成刷新?或者这是个坏主意?

def get_session(self):
    url= self.base_url + "/index.cfm"
    form_fields = {
      "email": "user@example.com",
      "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)

1 个答案:

答案 0 :(得分:0)

'lock'可以是'接近到期'标志加上活动表单提交的计数器(在提交开始时递增,在结束时递减)。该标志可以是对到期时间的简单检查,但计数器需要在db中。

如果设置了标志且计数器非零,则阻止开始新的过帐(例如使用while循环)。只有最后一个活动发布才会在递减计数器之前刷新cookie(从1到0)。

但是,将“实时”请求锁定的时间过长可能会导致您的应用实例因超出时间限制而被杀死(例如,如果平均45秒有时超过60)。

可能的解决方案是将实际发布推送到任务队列。如果发布被锁定,您只需要“失败”所有任务执行,GAE将自动重新尝试它们(暂时) - 任务应该在刷新cookie并解除锁定后自动传递。缺点:由于任务失败,这会在日志中产生一些噪音。此外,非常高的流量可能导致超出任务队列限制。

另一种可能性是在帖子接近过期并且没有其他帖子正在进行/等待之后先抢先刷新cookie。缺点:无法保证工作 - 如果请求流量足够高,在到期前无法找到这样的“空闲”点。

我可以想到在流量峰值期间处理锁定的唯一可靠方法是使用数据存储来“缓冲”在锁定解除后您将重放的发布作业(同样,任务队列将是一种简单的方法触发重播操作。)