gamecloud
Version:
game logic server over cloud
180 lines (158 loc) • 6.04 kB
JavaScript
/**
* Created by Administrator on 2017-05-13.
*/
let facade = require('../../Facade')
let {UserStatus} = facade.const
/**
* 索引服对应的门面类
*/
class CoreOfIndex extends facade.CoreOfBase
{
constructor($env){
super($env);
this.testRoute = new Set(); //直连测试服的openid列表
//中间件设定 - 注意不要覆盖父类构造函数已经做出的设定
this.middlewareSetting.default = ['parseParams', 'commonHandle'];
}
/**
* 映射自己的服务器类型数组,提供给核心类的类工厂使用
* @returns {Array}
*
* @note 索引服务器mapping取固定值
*/
static get mapping() {
return ['CoreOfIndex'];
}
static set mapping(val) {
}
routeList(){
let ret = [];
this.testRoute.forEach((item, sameItem, s)=>{
ret.push(item);
})
if(ret.length == 0){
ret.push('添加测试路由');
}
return ret;
}
async Start(app){
await super.Start(app);
//缓存管理器
this.cacheMgr = new facade.tools.cache(this);
console.time(`${this.options.serverType}${this.options.serverId} Load Db`);
await this.service.dailyactivity.loadDb(); //载入世界Boss活动信息
this.loadAllUsers(()=>{
console.timeEnd(`${this.options.serverType}${this.options.serverId} Load Db`);
console.log(`${this.options.serverType}.${this.options.serverId}: 数据载入完成,准备启动网络服务...`);
this.StartSocketServer(app);
});
//世界Boss活动检测,只在Index Server上进行
this.autoTaskMgr.addCommonMonitor(fo=>{
fo.service.dailyactivity.tick();
return false;
});
}
/**
* 根据DomainId列表,批量查询并返回用户对象列表
* @param {*} list 传入openid集合,注意并没有携带域信息,因为我们认为社交好友是可以同时注册多个服的
* @returns 返回键值对集合形式的对象: domain.openid: user
*/
async getUserIndexOfAll(list){
let ret = {};
let query = this.cacheMgr.getObj(list);
if(!!query){
query.map(uo=>{
if(!!uo) { //由于对用户领域进行了猜测,这里要判断下查询结果是否为空
ret[`${uo.domain}.${uo.openid}`] = uo;
}
});
}
return ret;
}
/**
* 检索用户所在服务器信息, 如果是新用户则采用负载均衡模式分配目标服务器
* @param domain 登录域
* @param openid 验证域
*/
async getUserIndex(domain, openid, register=null) {
//计算用户唯一标识串
let domainId = `${domain}.${openid}`;
let uo = this.cacheMgr.getObj(domainId);
if(!!uo) {
uo.status = facade.tools.Indicator.inst(uo.status).unSet(UserStatus.isNewbie).value;
} else if(!!register) { //新用户注册
//检测逻辑服类型
if(!this.serversInfo[domain]) {//非法类型
return null;
}
let serverId = 0, sn = null;
if(!register.sid) {
//负载均衡
serverId = (facade.util.hashCode(domainId) % this.serverNum(domain)) + 1; //通过hash计算命中服务器编号
sn = `${domain}.${serverId}`;
//避免新用户进入不合适的服务器(人数超限或状态不正常)
let recy = 0, isFind = false;
while(recy++ < this.serverNum(domain)){//检测服务器人数和运行状况
let svr = this.service.servers.getServer(domain, serverId);
if(!!svr && this.service.servers.userNum[sn] < this.options.MaxRegister){
isFind = true;
break;
}
serverId = serverId % this.serverNum(domain) + 1; //循环递增
sn = `${domain}.${serverId}`;
}
if(!isFind) {
return null;
}
} else {
serverId = register.sid; //注册时指定了服务器编号
sn = `${domain}.${serverId}`;
}
//寻找到了合适的服务器,累计服务器人数
this.service.servers.userNum[sn] += 1;
//为注册用户预登记
this.setUserIndex(uo = {
hisGateNo: 1,
role: 1001,
name: '',
icon: '',
stype: domain,
sid: serverId,
score: 0,
status: UserStatus.isNewbie,
domain: domain,
openid: openid,
});
}
return uo;
}
/**
* 将用户对象存回缓存
* @param {*} uo
*/
setUserIndex(uo){
if(!!uo && uo.domain && uo.openid) {
this.cacheMgr.setObj(`${uo.domain}.${uo.openid}`, uo);
}
}
/**
* 加载全部用户索引
* @returns {Promise.<void>}
*/
async loadAllUsers(cb){
try{
//遍历所有服务器,以便加载所有用户的索引
for(let stype in this.serversInfo) {
for(let id in this.serversInfo[stype]){
let item = this.serversInfo[stype][id];
await this.service.servers.loadIndex(item.mysql, stype, id); //载入分服的用户
}
}
cb(); //外部传入的回调
}
catch(e){
console.error(e);
}
}
}
exports = module.exports = CoreOfIndex;