NetEase / pomelo-cn

The Chinese issues for pomelo.
38 stars 13 forks source link

关于app.route()方法的几个疑问 #216

Closed peterchen08 closed 11 years ago

peterchen08 commented 11 years ago

在最新版本的loarofpomelo demo中,对特殊的服务器类型指定了路由处理函数: // route configures app.route('area', routeUtil.area); app.route('connector', routeUtil.connector);

问题一:在servers.json中,如果某种类型的服务器数量大于1时,原则上是不是都必须指定该类请求的路由方法?毕竟不同的用户处在不同的进程当中,用户请求需要路由到对应的进程

问题二:指定的路由函数有何规范?demo源码中var routeFunc = function(session, msg, app, cb),我注意到基本上都是将当前的serverId传递给回调函数cb(null, serverId); 但是这个回调函数在哪里被调用的呢?我一直追踪不到

问题三:我自己做了个俄罗斯方块的demo,如果不设置路由app.route('tetis', routeUtil.tetis);程序能进行rpc远程方法的调用,但是设置之后对,请求的tettis remote remote方法时,rpc-server/dispatcher.js报错:Error: no such namespace:user

随后对分别对auth remote 及tetris remote远程调用测试,module.exports.route = function(msg, services, cb)函数的services对象跟踪输出分别如下:

auth remote(正确调用): services={ sys: { channelRemote: { app: [Object] }, sessionRemote: { app: [Object] } }, user: { authRemote: { app: [Object], secret: 'pomelo_session_secret', expire: -1 } } }

tetris remote(报错) services={ sys: { channelRemote: { app: [Object] }, sessionRemote: { app: [Object] } } } 对比之下发现少了user这个对象,所以报错:Error: no such namespace:user。 再对module.exports.route = function(msg, services, cb)函数的msg对象跟踪,输出如下:msg={ namespace: 'user', serverType: 'tetris', service: 'tetrisRemote', method: 'enterHall', args: [ { userId: '0.27408930915407836', serverId: 'connector-server-2', name: 'peter' } ] } 问题归结为:module.exports.route = function(msg, services, cb)中,msg参数中有namespace对象,services中namespace对象丢失。 请问这个namespace在哪里定义的?msg的namespace对象于services对象中的namespace是什么关系?我才程序大概在什么地方出错了呢?

这个bug让我纠结了几天时间了,一直找不到症结所在。

py8765 commented 11 years ago

问题一:是的,如果同一类型服务器数量大于1,则需要指定路由方法,不过不指定,pomelo内部也会根据一个默认的算法调度。 问题二:这个方法是在pomelo-rpc里面的client.js中的proxyCB方法里调用的 问题三:namespace是在pomelo-rpc里面的servers.js里面loadRemoteService方法,看情况是没有加载到你写的rpc 服务,你首先检查一下这个服务所在目录位置,然后是否有对应的服务器。

peterchen08 commented 11 years ago

@py8765 非常感谢! 我找到原因了,我在指定路由函数var routeFunc = function(session, msg, app, cb)时,返回的serverId出错了,本意是指向自定义的俄罗斯方块服务器,结果指向了connector服务器的id。

这里自我总结一下,方便碰到同样情况的朋友。 1)为分散服务器压力,在servers.json中对某类型的服务器进行设置: "tetris": [ {"id": "tetris-server-1", "host": "127.0.0.1", "port": 3352, "tetrisId": 1}, {"id": "tetris-server-2", "host": "127.0.0.1", "port": 3353, "tetrisId": 2}, {"id": "tetris-server-3", "host": "127.0.0.1", "port": 3354, "tetrisId": 3} ],

2)当某种类型的服务器数量大于1,这个时候需要手动设置路由规则,指定路由方法,在app.js中对除“master”外的其他所有类型服务器进行路由设置:app.route(服务器类型,路由方法)。 在路由方法 var routeFunc = function(session, msg, app, cb) 中,需要给出一个算法,将用户当前所在的该类型的服务器id提供给回调函数,这样才能将用户请求路由到正确的服务器进程当中。如:cb(null,'tetris-server-2')

3)事实上,当用户首次进行连接的时候,就应当为用户分配一个serverId,并将该serverId记录下来,保存到session当中。将来如果游戏断线重连,也应该连接到这个serverId。 我的demo中处理方法是为用户随机分配一个tetris server,并将服务器ID保存到session.serverId当中,当用户进行请求的时候,通过读取session.serverId,很方便就能在路由函数中定向了。