服务器定时器的管理优化
2016-10-09 17:55
471 查看
作为一个游戏服务器,必然有很多定时器的使用,算是游戏服务器开发的基础模块,我们经常需要在我们预期的某个时间点执行某项特定的操作。比如每天M点开启某个活动,N小时后之后刷新排行榜等等。这些功能通常需要定时器控制,之前我们的服务器代码中每加一个延迟执行的功能就启动一个定时器,这样到最后往往代码特别臃肿,而且定时器时稀缺资源,过多的定时器必然导致效率问题,于是要想办法优化。
想要优化定时器就要看定时器一共有多少种:
1.只执行一次的定时器,比如60秒后执行操作A。
2.循环执行的定时器,比如每隔30分钟执行一次操作B。
3.每日/每周/每月特定时间点执行一次的操作C。(eg.每天下午6点执行操作C)
我们要做的就是,把一整套需要定时器的操作整合到一个定时器管理器Manager里面,然后每次有新的定时器要添加,调用Add接口加到Manager里面,Manager只会启动一个定时器,它会自动寻找最近需要执行的定时器然后到时间点后处理相关逻辑。这样我们每次增加定时器操作就是往管理器里面添加一个操作就行了,其他的管理器会替我们解决。
我用一个列表储存需要管理的定时器对象列表,addTimerObj用来增加定时器对象。startTimer启动管理器的定时器,它会取最小的下次定时器触发时间以及对象列表(因为同一个时间点可能有多个事件),然后启动定时器,到点执行操作。
代码还有需要优化的点:
1.为了简单我用了列表存储,可以考虑其他更好的数据结构,比如使用类似libevent的最小堆。
2.我每次stopTimer再startTimer这点可以考虑优化。
3.我在每次getMinNextTimer的时候才过滤已经过期的定时器。
4.我暴露了TimerObj对象,可以在TimerManager里面增加一个接口,然后根据参数创建TimerObj,就不需要TimerObj给用户。
5. ...
使用很简单,创建一个TimerManager对象,然后需要增加的时候,创建一个TimerObj对象,把启动时间,间隔,以及回调传进去,然后调用addTimerObj加到TimerManager对象里面。
onlineCountingTimer = TimerObj(now_time, 5 * 60, lambda : self.onlineCounting())
self.timerManager.addTimerObj(onlineCountingTimer)
我之前还有一种做法,基于第三种定时器,在服务器启动的时候启动一个整点定时器。
像这种:
然后在各个Manager里面定义一个NewHour的接口,通过此NewHour调用。
这样,那些需要在整点执行的接口在各个Manger里面处理就好了
像这样。
不过考虑到代码逻辑的一致性,暂时没用这种方法,只用了TimerManager管理了所有的定时器。
注:有些接口是我们引擎封装的,我就不暴露出来了,权当是伪代码好了。对理解大意无影响。
想要优化定时器就要看定时器一共有多少种:
1.只执行一次的定时器,比如60秒后执行操作A。
2.循环执行的定时器,比如每隔30分钟执行一次操作B。
3.每日/每周/每月特定时间点执行一次的操作C。(eg.每天下午6点执行操作C)
我们要做的就是,把一整套需要定时器的操作整合到一个定时器管理器Manager里面,然后每次有新的定时器要添加,调用Add接口加到Manager里面,Manager只会启动一个定时器,它会自动寻找最近需要执行的定时器然后到时间点后处理相关逻辑。这样我们每次增加定时器操作就是往管理器里面添加一个操作就行了,其他的管理器会替我们解决。
from common import Timer from util import TimeUtil from base.Defines import * class TimerObj(object): """封装一个定时器对象""" def __init__(self, start_time, interval, callback): """ :param start_time:定时器开始时间 :param interval:定时器间隔,如果只执行一次,填0 :param callback:触发定时器时执行的函数 :return: """ super(TimerObj, self).__init__() self.start = start_time self.interval = interval self.callback = callback def getEndTime(self): if self.interval <= 0: return self.start return None def getNextTime(self): now_time = int(TimeUtil.now_time()) if now_time < self.start: return self.start else: if self.getEndTime() is not None: return None num = 0 while self.start + num <= now_time: num += self.interval return self.start + num class TimerManager(object): """管理所有的定时器""" def __init__(self): super(TimerManager, self).__init__() self.timer_list = [] self.timer = None def addTimerObj(self, obj): self.timer_list.append(obj) self.stopTimer() self.startTimer() def removeTimeObj(self, type): pass def getMinNextTimer(self): min_next = INT_MAX result = [] self.timer_list = filter(lambda x:x.getNextTime() is not None, self.timer_list) for obj in self.timer_list: next = obj.getNextTime() if next < min_next: min_next = next result = [] result.append(obj) elif next == min_next: result.append(obj) if min_next == INT_MAX: return None,None #print "getMinNextTimer",min_next,int(TimeUtil.now_time()) return min_next, result def startTimer(self): timestamp, objlist = self.getMinNextTimer() if timestamp is None: return self.stopTimer() delay = int(timestamp) - int(TimeUtil.now_time()) if delay == 0: delay = 1 self.timer = Timer.addTimer(delay, lambda :self.callTimer(objlist)) def callTimer(self, objlist): #print "callTimer",int(TimeUtil.now_time()) self.startTimer() for obj in objlist: obj.callback() def stopTimer(self): if self.timer is not None: self.timer.cancel() self.timer = None
我用一个列表储存需要管理的定时器对象列表,addTimerObj用来增加定时器对象。startTimer启动管理器的定时器,它会取最小的下次定时器触发时间以及对象列表(因为同一个时间点可能有多个事件),然后启动定时器,到点执行操作。
代码还有需要优化的点:
1.为了简单我用了列表存储,可以考虑其他更好的数据结构,比如使用类似libevent的最小堆。
2.我每次stopTimer再startTimer这点可以考虑优化。
3.我在每次getMinNextTimer的时候才过滤已经过期的定时器。
4.我暴露了TimerObj对象,可以在TimerManager里面增加一个接口,然后根据参数创建TimerObj,就不需要TimerObj给用户。
5. ...
使用很简单,创建一个TimerManager对象,然后需要增加的时候,创建一个TimerObj对象,把启动时间,间隔,以及回调传进去,然后调用addTimerObj加到TimerManager对象里面。
onlineCountingTimer = TimerObj(now_time, 5 * 60, lambda : self.onlineCounting())
self.timerManager.addTimerObj(onlineCountingTimer)
我之前还有一种做法,基于第三种定时器,在服务器启动的时候启动一个整点定时器。
像这种:
def main(): struct_time = time.localtime() min, sec = struct_time.tm_min, struct_time.tm_sec remain = 3600 - (min * 60 + sec) Timer.addTimer(remain, lambda: self.newhour_callback()) def newhour_callback(self): import manager.DaysManager as DaysManager DaysManager.NewHour() Timer.addRepeatTimer(3600, lambda: NewHour()) def NewHour(): """每小时整点会执行到这里"""" DaysManager.NewHour() ... ...
然后在各个Manager里面定义一个NewHour的接口,通过此NewHour调用。
这样,那些需要在整点执行的接口在各个Manger里面处理就好了
def NewHour(self): struct_time = time.localtime() hour = struct_time.tm_hour _logger.info("NewHour: "+str(hour)) if hour == 0: # 0点刷新 self.refresh_new_task()
像这样。
不过考虑到代码逻辑的一致性,暂时没用这种方法,只用了TimerManager管理了所有的定时器。
注:有些接口是我们引擎封装的,我就不暴露出来了,权当是伪代码好了。对理解大意无影响。
相关文章推荐
- 服务器定时器的管理优化(思路借鉴)
- 二、服务器优化(6)WSRM管理多个实例
- 记录一个关于互联网、网页设计、Web开发、服务器运维优化、项目管理、网站运营、网站安全的网站
- Windows Server 2003网络配置与管理 优化服务器的性能
- 高性能网络服务器6--reactor反应堆与定时器管理
- 二、服务器优化(4)资源调控器管理工作负荷
- 优化管理Eclipse插件
- 服务器管理的标准SMASH
- 公司文件服务器管理,让用户快速找到需要的文件。
- UNIX下DNS服务器之管理维护篇
- 怎样优化Apache服务器的性能
- 实验四:Telnet远程登录服务器的安装、管理及Telnet客户端的应用
- BT发布服务器和流量管理系统安装指南
- [ZT]Apusic应用服务器的性能调节_JVM优化
- 使用HOST-RESOURCES-MIB和RFC1213-MIB通过SNMP管理服务器
- [导入]服务器终极安全设置与优化指南
- 优化 Web 服务器计算机和特定应用程序的配置文件以符合您的特定需要
- [ZT]优化配置mysql服务器
- 图解Web和FTP服务器安全管理配置
- 针对Win2000优化Web服务器性能