rename old

This commit is contained in:
Jalin
2019-05-14 13:21:25 +08:00
parent 8d4ea3066a
commit f49b081bc5
77 changed files with 11 additions and 254 deletions

234
old_py12306/helpers/cdn.py Normal file
View File

@@ -0,0 +1,234 @@
import random
import json
from datetime import timedelta
from os import path
from py12306.cluster.cluster import Cluster
from py12306.config import Config
from py12306.app import app_available_check
from py12306.helpers.api import API_CHECK_CDN_AVAILABLE, HOST_URL_OF_12306
from py12306.helpers.func import *
from py12306.helpers.request import Request
from py12306.log.common_log import CommonLog
@singleton
class Cdn:
"""
CDN 管理
"""
items = []
available_items = []
unavailable_items = []
recheck_available_items = []
recheck_unavailable_items = []
retry_time = 3
is_ready = False
is_finished = False
is_ready_num = 10 # 当可用超过 10已准备好
is_alive = True
is_recheck = False
safe_stay_time = 0.2
retry_num = 1
thread_num = 5
check_time_out = 3
last_check_at = 0
save_second = 5
check_keep_second = 60 * 60 * 24
def __init__(self):
self.cluster = Cluster()
self.init_config()
create_thread_and_run(self, 'watch_cdn', False)
def init_data(self):
self.items = []
self.available_items = []
self.unavailable_items = []
self.is_finished = False
self.is_ready = False
self.is_recheck = False
def init_config(self):
self.check_time_out = Config().CDN_CHECK_TIME_OUT
def update_cdn_status(self, auto=False):
if auto:
self.init_config()
if Config().is_cdn_enabled():
self.run()
else:
self.destroy()
@classmethod
def run(cls):
self = cls()
app_available_check()
self.is_alive = True
self.start()
pass
def start(self):
if not Config.is_cdn_enabled(): return
self.load_items()
CommonLog.add_quick_log(CommonLog.MESSAGE_CDN_START_TO_CHECK.format(len(self.items))).flush()
self.restore_items()
for i in range(self.thread_num): # 多线程
create_thread_and_run(jobs=self, callback_name='check_available', wait=False)
def load_items(self):
with open(Config().CDN_ITEM_FILE, encoding='utf-8') as f:
for line, val in enumerate(f):
self.items.append(val.rstrip('\n'))
def restore_items(self):
"""
恢复已有数据
:return: bool
"""
result = False
if path.exists(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE):
with open(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE, encoding='utf-8') as f:
result = f.read()
try:
result = json.loads(result)
except json.JSONDecodeError as e:
result = {}
# if Config.is_cluster_enabled(): # 集群不用同步 cdn
# result = self.get_data_from_cluster()
if result:
self.last_check_at = result.get('last_check_at', '')
if self.last_check_at: self.last_check_at = str_to_time(self.last_check_at)
self.available_items = result.get('items', [])
self.unavailable_items = result.get('fail_items', [])
CommonLog.add_quick_log(CommonLog.MESSAGE_CDN_RESTORE_SUCCESS.format(self.last_check_at)).flush()
return True
return False
# def get_data_from_cluster(self):
# available_items = self.cluster.session.smembers(Cluster.KEY_CDN_AVAILABLE_ITEMS)
# last_time = self.cluster.session.get(Cluster.KEY_CDN_LAST_CHECK_AT, '')
# if available_items and last_time:
# return {'items': available_items, 'last_check_at': last_time}
# return False
def is_need_to_recheck(self):
"""
是否需要重新检查 cdn
:return:
"""
if self.last_check_at and (
time_now() - self.last_check_at).seconds > self.check_keep_second:
return True
return False
def get_unchecked_item(self):
if not self.is_recheck:
items = list(set(self.items) - set(self.available_items) - set(self.unavailable_items))
else:
items = list(set(self.items) - set(self.recheck_available_items) - set(self.recheck_unavailable_items))
if items: return random.choice(items)
return None
def check_available(self):
while True and self.is_alive:
item = self.get_unchecked_item()
if not item: return self.check_did_finished()
self.check_item_available(item)
def watch_cdn(self):
"""
监控 cdn 状态,自动重新检测
:return:
"""
while True:
if self.is_alive and not self.is_recheck and self.is_need_to_recheck(): # 重新检测
self.is_recheck = True
self.is_finished = False
CommonLog.add_quick_log(
CommonLog.MESSAGE_CDN_START_TO_RECHECK.format(len(self.items), time_now())).flush()
for i in range(self.thread_num): # 多线程
create_thread_and_run(jobs=self, callback_name='check_available', wait=False)
stay_second(self.retry_num)
def destroy(self):
"""
关闭 CDN
:return:
"""
CommonLog.add_quick_log(CommonLog.MESSAGE_CDN_CLOSED).flush()
self.is_alive = False
self.init_data()
def check_item_available(self, item, try_num=0):
session = Request()
response = session.get(API_CHECK_CDN_AVAILABLE.format(item), headers={'Host': HOST_URL_OF_12306},
timeout=self.check_time_out,
verify=False)
if response.status_code == 200:
if not self.is_recheck:
self.available_items.append(item)
else:
self.recheck_available_items.append(item)
if not self.is_ready: self.check_is_ready()
elif try_num < self.retry_num: # 重试
stay_second(self.safe_stay_time)
return self.check_item_available(item, try_num + 1)
else:
if not self.is_recheck:
self.unavailable_items.append(item)
else:
self.recheck_unavailable_items.append(item)
if not self.is_recheck and (
not self.last_check_at or (time_now() - self.last_check_at).seconds > self.save_second):
self.save_available_items()
stay_second(self.safe_stay_time)
def check_did_finished(self):
self.is_ready = True
if not self.is_finished:
self.is_finished = True
if self.is_recheck:
self.is_recheck = False
self.available_items = self.recheck_available_items
self.unavailable_items = self.recheck_unavailable_items
self.recheck_available_items = []
self.recheck_unavailable_items = []
CommonLog.add_quick_log(CommonLog.MESSAGE_CDN_CHECKED_SUCCESS.format(len(self.available_items))).flush()
self.save_available_items()
def save_available_items(self):
self.last_check_at = time_now()
data = {'items': self.available_items, 'fail_items': self.unavailable_items,
'last_check_at': str(self.last_check_at)}
with open(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE, 'w') as f:
f.write(json.dumps(data))
# if Config.is_master():
# self.cluster.session.sadd(Cluster.KEY_CDN_AVAILABLE_ITEMS, self.available_items)
# self.cluster.session.set(Cluster.KEY_CDN_LAST_CHECK_AT, time_now())
def check_is_ready(self):
if len(self.available_items) > self.is_ready_num:
self.is_ready = True
else:
self.is_ready = False
@classmethod
def get_cdn(cls):
self = cls()
if self.is_ready and self.available_items:
return random.choice(self.available_items)
return None
if __name__ == '__main__':
# Const.IS_TEST = True
Cdn.run()
while not Cdn().is_finished:
stay_second(1)