应用场景:游戏开发中,服务器经常需要调整时间,比如测活动,要测完整流程需要频繁修改时间
实现方案
1.调整整机时间,这个操作成本太高,会影响到主机的所有用户
2.直接应用层做虚拟时间,需要调用特定接口,如果有逻辑直接调用了系统接口,那么时间就会不一致
3.将server组做成docker,直接修改docker的时间,有个副作用,修改docker时间会将宿主机时间也修改
4.用虚拟机框定server组,可以直接修改时间,单用户单虚拟机,有些门槛,一个策划或者qa会验证n个版本,这样需要n个虚拟机,不好维护
5.faketime,给特定进程隔离的时间定制,可以是一个docker进程,也可以是一组server进程,框定的一个进程范围公用一个时间,隔离性很好
最终选择:
基于以上对比,可以发现faketime是最优选择,我们当前的server没有放到docker里,所以选择把server组框定共用一个faketime
上代码:
下载faketime,make && make install && make test
faketime起作用就是两个文件,一个是so文件,另一个rc配置文件
要想一组进程都共用一个faketime,就是让这些进程启动时都应用同一个faketime.rc文件,同时为了让框定的所有进程时间尽可能一致,这是不能给定一个具体时间,因为进程有启动先后,启动快慢,这样指定绝对时间的话最终其实是不一致的。因此只能给定相对时间,就是相对当前系统时间给一个偏移值,在各进程启动后,按照这个偏移值来定制时间,这样不管启动先后快慢,都是跟系统时间相同的偏移 ,这样就可以实现所有进程是同一个虚拟时间。另外还要指定不要缓存faketime,要实时监控rc文件中时间的修改,rc文件一变动,应用faketime的进程就必须响应新的虚拟时间
#run_server.sh 启动脚本
#!/bin/bash
BOOT_LOG="./boot.log"
function run_server()
{
ERL_PARAM=$1
APP_NAME=$2
if [ $S_ENV = 'dev' ]; then
LD_PRELOAD=../tools/faketime/libfaketime.so.1 FAKETIME_TIMESTAMP_FILE=../tools/faketime/faketime.rc FAKETIME_CACHE_DURATION=0 erl -boot start_sasl ${ERL_PARAM} -s ${APP_NAME}
echo "`date +'%Y-%m-%d %H:%M:%S'`|start ${APP_NAME} in $S_ENV with faketime" >> $BOOT_LOG
else
erl -boot start_sasl ${ERL_PARAM} -s ${APP_NAME}
echo "`date +'%Y-%m-%d %H:%M:%S'`|start ${APP_NAME} in $S_ENV normally" >> $BOOT_LOG
fi
}
#time_change.sh 修改时间脚本
#!/bin/bash
target_time=`date -d "$1" +%s`
now_time=`date +%s`
echo "+$(($target_time - $now_time))" > tools/faketime/faketime.rc
chmod 777 tools/faketime/faketime.rc
#start_all.sh
if [ $# = 1 ]; then
./time_change.sh $1
else
echo "+0 x1" > tools/faketime/faketime.rc
fi
#start.sh
#!/bin/bash
source ../run_server.sh
run_server "${ERL_PARAM}" "${APP_NAME}"
#get_localtime.sh 查看当前server进程组时间
#!/bin/bash
LD_PRELOAD=tools/faketime/libfaketimeMT.so.1 FAKETIME_TIMESTAMP_FILE=tools/faketime/faketime.rc FAKETIME_CACHE_DURATION=0 date
注意点:
1.LD_PRELOAD=../tools/faketime/libfaketime.so.1 FAKETIME_TIMESTAMP_FILE=../tools/faketime/faketime.rc some_proc
这里指定库文件和faketime配置文件,要想一个进程组都是统一时间,需要指定相同的faketime.rc
2.FAKETIME_CACHE_DURATION=0或者FAKETIME_NO_CACHE=1表示无延迟响应配置修改
3.将绝对时间转换为相对时间偏移
target_time=`date -d "$1" +%s`
now_time=`date +%s`
echo "+$(($target_time - $now_time))" > tools/faketime/faketime.rc