# -*- coding: utf-8 -*- #!/usr/bin/python import pymysql import hashlib import json import urllib.request import base64 import tornado.ioloop import tornado.web import time import datetime import redis import os CONFIG_DIR = '' def IsOnlineEnv(): return os.getenv("SERVER_ENV"); if (IsOnlineEnv()): CONFIG_DIR = '/var/data/conf_test/game2001api_rankserver/config' else: CONFIG_DIR = '../config' def info(msg): print(str(datetime.datetime.now()) + '[INFO] ' + msg) def take_kills(elem): return elem[3] def take_alive_time(elem): return elem[4] def take_harms(elem): return elem[5] def take_win_times(elem): return elem[6] def take_game_times(elem): return elem[7] def safeDiv(a, b): if b == 0: return 0 else: return a / b def getRedis(): redis_conf = json.loadsmysql_conf = json.loads(open(CONFIG_DIR + '/rankserver.redis.cluster.json', 'r').read()) for conf in redis_conf: r = redis.Redis(host = conf['host'], port = conf['port'], password = conf['passwd'], charset = 'utf8' ) return r; def getDaySeconds(time_val, incdays): time_zone = 8 dayseconds = int((time_val + time_zone * 3600)/3600/24 + incdays) * 3600 * 24 - 3600 * time_zone; return dayseconds #刷新数据 def refreshData(row, kill_list, alive_list, harm_list, rate_list, win_list): kill = safeDiv(row[3], row[7]) alive_time = safeDiv(row[4], row[7]) harm = safeDiv(row[5], row[7]) win_times = safeDiv(row[6], row[7]) kill_list.append((row[0], row[1].decode('utf-8'), row[2], kill, alive_time, harm, win_times, row[6])) kill_list.sort(key=take_kills, reverse=True) if (len(kill_list) > 50): del kill_list[50:] alive_list.append((row[0], row[1].decode('utf-8'), row[2], kill, alive_time, harm, win_times, row[6])) alive_list.sort(key=take_alive_time, reverse=True) if (len(alive_list) > 50): del alive_list[50:] harm_list.append((row[0], row[1].decode('utf-8'), row[2], kill, alive_time, harm, win_times, row[6])) harm_list.sort(key=take_harms, reverse=True) if (len(harm_list) > 50): del harm_list[50:] rate_list.append((row[0], row[1].decode('utf-8'), row[2], kill, alive_time, harm, win_times, row[6])) rate_list.sort(key=take_win_times, reverse=True) if (len(rate_list) > 50): del rate_list[50:] win_list.append((row[0], row[1].decode('utf-8'), row[2], kill, alive_time, harm, win_times, row[6])) win_list.sort(key=take_game_times, reverse=True) if (len(win_list) > 50): del win_list[50:] #更新排行榜 def updateRank(r, kill_list, alive_list, harm_list, rate_list, win_list): kill_list.sort(key=take_kills, reverse=True) kill_rank = [] for kill_index in range(min(50, len(kill_list))): kill_rank.append(kill_list[kill_index]) r.set("game2001api: kill_rank", json.dumps(kill_rank)) alive_list.sort(key=take_alive_time, reverse=True) alive_rank = [] for alive_index in range(min(50, len(alive_list))): alive_rank.append(alive_list[alive_index]) r.set("game2001api: alive_rank", json.dumps(alive_rank)) harm_list.sort(key=take_harms, reverse=True) harm_rank = [] for harm_index in range(min(50, len(harm_list))): harm_rank.append(harm_list[harm_index]) r.set("game2001api: harm_rank", json.dumps(harm_rank)) rate_list.sort(key=take_win_times, reverse=True) rate_rank = [] for rate_index in range(min(50, len(rate_list))): rate_rank.append(rate_list[rate_index]) r.set("game2001api: rate_rank", json.dumps(rate_rank)) win_list.sort(key=take_game_times, reverse=True) win_rank = [] for win_index in range(min(50, len(win_list))): win_rank.append(win_list[win_index]) r.set("game2001api: win_rank", json.dumps(win_rank)) #每日定时读取mysql里的数据生成排行榜写入redis后php读取redis返回客户端显示 def dayReadMysqlData(rushtime): mysql_conf = json.loads(open(CONFIG_DIR + '/rankserver.mysql.cluster.json', 'r').read()) kill_list = [] alive_list = [] harm_list = [] rate_list = [] win_list = [] for conf in mysql_conf: conn = pymysql.connect(host = conf['host'], port = conf['port'], user = conf['user'], passwd = conf['passwd'], db = 'gamedb2001_' + str(conf['instance_id']), charset = 'utf8' ) cursor = conn.cursor() last_idx = 0 temp_idx = 0 while 1: cursor.execute('SELECT accountid, user_name, avatar_url, kills, alive_time,' ' harm, win_times, game_times, idx FROM user WHERE idx > %s LIMIT 0, 1000' % (last_idx)) has_data = False for row in cursor: refreshData(row, kill_list, alive_list, harm_list, rate_list, win_list) temp_idx = int(row[8]) if (temp_idx > last_idx) : last_idx = int(row[8]) if not has_data: break r = getRedis() updateRank(r, kill_list, alive_list, harm_list, rate_list, win_list) tornado.ioloop.IOLoop.current().call_later(getDaySeconds(time.time(), 1) + rushtime, lambda : dayReadMysqlData(rushtime) ) #每5分钟读取mysql里发生改变过的数据更新排行榜 def readMysqlData(rushtime): mysql_conf = json.loads(open(CONFIG_DIR + '/rankserver.mysql.cluster.json', 'r').read()) r = getRedis() kill_list_str = r.get("game2001api: kill_rank") if (not kill_list_str): kill_list = [] else: kill_list = json.loads(kill_list_str) alive_list_str = r.get("game2001api: alive_rank") if (not alive_list_str): alive_list = [] else: alive_list = json.loads(alive_list_str) harm_list_str = r.get("game2001api: harm_rank") if (not harm_list_str): harm_list = [] else: harm_list = json.loads(harm_list_str) rate_list_str = r.get("game2001api: rate_rank") if (not rate_list_str): rate_list = [] else: rate_list = json.loads(rate_list_str) win_list_str = r.get("game2001api: win_rank") if (not win_list_str): win_list = [] else: win_list = json.loads(win_list_str) for conf in mysql_conf: conn = pymysql.connect(host = conf['host'], port = conf['port'], user = conf['user'], passwd = conf['passwd'], db = 'gamedb2001_' + str(conf['instance_id']), charset = 'utf8' ) cursor = conn.cursor() last_idx = 0 temp_idx = 0 flag = 0 while 1: cursor.execute('SELECT accountid, user_name, avatar_url, kills, alive_time,' ' harm, win_times, game_times, idx, modify_time FROM user ' ' WHERE modify_time > %s AND idx > %s LIMIT 0, 1000' % (time.time() - 300, last_idx)) has_data = False for row in cursor: for rowKill in kill_list: if (rowKill[0] == row[0]): flag = 1 break if (flag != 1): refreshData(row, kill_list, alive_list, harm_list, rate_list, win_list) temp_idx = int(row[8]) if (temp_idx > last_idx) : last_idx = int(row[8]) if not has_data: break updateRank(r, kill_list, alive_list, harm_list, rate_list, win_list) tornado.ioloop.IOLoop.current().call_later(rushtime, lambda : readMysqlData(rushtime) ) class SelfCheckingHandler(tornado.web.RequestHandler): def get(self): self.write(json.dumps({ 'errcode': 0, 'errmsg': '', 'healthy': 1, 'max_rundelay': 10 })) def make_app(): return tornado.web.Application([ (r"/webapp/index[\.]php", SelfCheckingHandler), ]) if __name__ == "__main__": conf = json.loads(open(CONFIG_DIR + '/rankserver.json', 'r').read()) app = make_app() app.listen(conf['listen_port']) conf['rushtime'] = 300 tornado.ioloop.IOLoop.current().call_later(conf['rushtime'], lambda : readMysqlData(conf['rushtime']) ) conf['day_rushtime'] = 17 * 3600 tornado.ioloop.IOLoop.current().call_later(getDaySeconds(time.time(), 1) + conf['day_rushtime'], lambda : dayReadMysqlData(conf['day_rushtime']) ) tornado.ioloop.IOLoop.current().start()