|
@@ -83,22 +83,31 @@ _event_loop = None
|
|
|
|
|
|
# todo: use lock to avoid thread race condition
|
|
|
class HttpHandler:
|
|
|
+ """基于HTTP的后端Handler实现
|
|
|
+
|
|
|
+ .. note::
|
|
|
+ 对 HttpHandler._webio_sessions 的访问不需要加锁, See:
|
|
|
+ https://stackoverflow.com/questions/1312331/using-a-global-dictionary-with-threads-in-python
|
|
|
+
|
|
|
+ """
|
|
|
# type: Dict[str, Session]
|
|
|
_webio_sessions = {} # WebIOSessionID -> WebIOSession()
|
|
|
_webio_expire = LRUDict() # WebIOSessionID -> last active timestamp。按照最后活跃时间递增排列
|
|
|
+ _webio_expire_lock = threading.Lock()
|
|
|
|
|
|
_last_check_session_expire_ts = 0 # 上次检查session有效期的时间戳
|
|
|
|
|
|
- DEFAULT_SESSION_EXPIRE_SECONDS = 60 # 超过60s会话不活跃则视为会话过期
|
|
|
- SESSIONS_CLEANUP_INTERVAL = 20 # 清理过期会话间隔(秒)
|
|
|
WAIT_MS_ON_POST = 100 # 在处理完POST请求时,等待WAIT_MS_ON_POST毫秒再读取返回数据。Task的command可以立即返回
|
|
|
|
|
|
+ DEFAULT_SESSION_EXPIRE_SECONDS = 60 # 默认会话过期时间
|
|
|
+ DEFAULT_SESSIONS_CLEANUP_INTERVAL = 20 # 默认清理过期会话间隔(秒)
|
|
|
+
|
|
|
@classmethod
|
|
|
def _remove_expired_sessions(cls, session_expire_seconds):
|
|
|
- logger.debug("removing expired sessions")
|
|
|
"""清除当前会话列表中的过期会话"""
|
|
|
+ logger.debug("removing expired sessions")
|
|
|
while cls._webio_expire:
|
|
|
- sid, active_ts = cls._webio_expire.popitem(last=False)
|
|
|
+ sid, active_ts = cls._webio_expire.popitem(last=False) # 弹出最不活跃的session info
|
|
|
|
|
|
if time.time() - active_ts < session_expire_seconds:
|
|
|
# 当前session未过期
|
|
@@ -128,6 +137,18 @@ class HttpHandler:
|
|
|
context.set_header('Access-Control-Expose-Headers', 'webio-session-id')
|
|
|
context.set_header('Access-Control-Max-Age', str(1440 * 60))
|
|
|
|
|
|
+ def interval_cleaning(self):
|
|
|
+ # clean up at intervals
|
|
|
+ cls = type(self)
|
|
|
+ need_clean = False
|
|
|
+ with cls._webio_expire_lock:
|
|
|
+ if time.time() - cls._last_check_session_expire_ts > self.session_cleanup_interval:
|
|
|
+ cls._last_check_session_expire_ts = time.time()
|
|
|
+ need_clean = True
|
|
|
+
|
|
|
+ if need_clean:
|
|
|
+ cls._remove_expired_sessions(self.session_expire_seconds)
|
|
|
+
|
|
|
def handle_request(self, context: HttpContext):
|
|
|
"""处理请求"""
|
|
|
cls = type(self)
|
|
@@ -189,10 +210,8 @@ class HttpHandler:
|
|
|
pass
|
|
|
|
|
|
cls._webio_expire[webio_session_id] = time.time()
|
|
|
- # clean up at intervals
|
|
|
- if time.time() - cls._last_check_session_expire_ts > self.session_cleanup_interval:
|
|
|
- cls._last_check_session_expire_ts = time.time()
|
|
|
- self._remove_expired_sessions(self.session_expire_seconds)
|
|
|
+
|
|
|
+ self.interval_cleaning()
|
|
|
|
|
|
context.set_content(webio_session.get_task_commands(), json_type=True)
|
|
|
|
|
@@ -227,7 +246,7 @@ class HttpHandler:
|
|
|
self.applications = make_applications(applications)
|
|
|
self.check_origin = check_origin
|
|
|
self.session_expire_seconds = session_expire_seconds or cls.DEFAULT_SESSION_EXPIRE_SECONDS
|
|
|
- self.session_cleanup_interval = session_cleanup_interval or cls.SESSIONS_CLEANUP_INTERVAL
|
|
|
+ self.session_cleanup_interval = session_cleanup_interval or cls.DEFAULT_SESSIONS_CLEANUP_INTERVAL
|
|
|
|
|
|
for target in self.applications.values():
|
|
|
register_session_implement_for_target(target)
|