当前位置: 首页 > 工具软件 > Pomelo > 使用案例 >

Pomelo Route

苗冯浩
2023-12-01

route是用来标识一个具体服务或客户端接受服务端推送消息的位置,对服务器来说,其形式一般是:chat.chatHandler.send,其中chat是服务器类型,chatHandler是chat服务器中定义的一个Handler,send则是这个Handler中的一个handler方法。

对客户端来说,其路由形式一般为onXXX,当服务端请求到达后,前端服务器会将用户客户端请求派发到后端服务器,这种派发需要一个路由函数router,可以粗略地认为router是根据用户的session以及其请求内容做一些运算后,将其映射到一个具体的应用服务器ID。

可以通过application的route调用给某一类型的服务器配置其router。若不配置的话,Pomelo会使用一个默认的router。

Pomelo默认的路由函数是使用session里面的uid字段,计算uid字段的crc32校验码,然后用这个校验码作为key,跟同类应用服务器数目取余,得到要路由到的服务器编号。注意这里有一个陷进,如果session没有绑定uid的话,此时uid字段为undefined,可能会造成所有请求都路由到同一台服务器,所以在实际开发中还是需要自己来配置router。

路由配置

当应用只有很少用户时只需一台服务器即可,但随着用户的增加,一台服务器无法承受同一时刻巨大的访问量,此时需要对服务器进行伸缩扩充。扩充服务器分布两部,首先需要修改服务器配置文件,添加服务器配置信息。其次,配置路由。

服务器配置

$ vim game-server/config/servers.json

例如:开发环境下配置一台网关服务器,配置三台前端服务器,配置三台聊天服务器。

{
  "development":{
    "gate": [
      {"id": "gate-server-1", "host": "127.0.0.1", "clientPort": 3014, "frontend": true}
    ],
    "connector": [
      {"id": "connector-server-1", "host": "127.0.0.1", "port": 4050, "clientHost": "127.0.0.1", "clientPort": 3050, "frontend": true},
      {"id": "connector-server-2", "host": "127.0.0.1", "port": 4051, "clientHost": "127.0.0.1", "clientPort": 3051, "frontend": true},
      {"id": "connector-server-3", "host": "127.0.0.1", "port": 4052, "clientHost": "127.0.0.1", "clientPort": 3052, "frontend": true}
    ],
    "chat": [
      {"id":"chat-server-1", "host": "127.0.0.1", "port": 5050},
      {"id":"chat-server-2", "host": "127.0.0.1", "port": 5051},
      {"id":"chat-server-3", "host": "127.0.0.1", "port": 5052}
    ]
  }
}

路由配置

当配置了不同类型的多台服务器时,此时就需要考虑用户请求的服务器分配问题。

对于网关服务器,由于存在多台前端服务器。所以需要从中选择一台服务器信息进行返回。可以使用用户的uid的crc32的校验码与前端服务器的个数取余,从而计算出一个前端服务器。

const index = Math.abs(crc.crc32(uid)) % connectors.length;
const connector = connectors[index];

当客户端请求到来时因为有多台聊天服务器,需要选择由哪台聊天服务器来服务,也就时前端服务器会将客户端请求路由到哪个后端服务器上。可使用同样的服务器分配策略。

const pomelo = require('pomelo');
const crc = require('crc');
const path = require('path');

/**初始化应用*/
const app = pomelo.createApp();

//上下文变量存取
app.set('name', 'test');

//全局配置
app.configure('production|development',  function(){
    //加载MySQL数据库
    app.loadConfig("mysql", path.join(app.getBase(), "config/mysql.json"));
    const host = app.get("mysql").host;//获取配置
    console.log("mysql config: host = %s",host);
});

//网关服务器配置
app.configure('production|development',  'gate', function(){
    //连接配置
    app.set('connectorConfig',
        {
            connector : pomelo.connectors.hybridconnector,
            heartbeat : 3,
            useDict : true,
            useProtobuf : true
        });
});

//前端服务器配置
app.configure('production|development',  'connector', function(){
    //连接配置
    app.set('connectorConfig',
    {
      connector : pomelo.connectors.hybridconnector,
      heartbeat : 3,
      useDict : true,
      useProtobuf : true
    });
});

//聊天服务器配置
app.configure("production|development", "chat",function(){
    //路由配置
    app.route("chat", function(session, msg, app, cb){
        const servers = app.getServersByType("chat");
        if(!servers || servers.length===0){
            cb(new Error("can not find chat servers"));
            return;
        }
        const val = session.get("rid");
        if(!val){
            cb(new Error("session rid is not find"));
            return;
        }
        const index = Math.abs(crc.crc32(val)) % servers.length;
        const server = servers[index];
        cb(null, server.id);
    });
    //过滤配置
    app.filter(pomelo.timeout());
});

//开启应用
app.start();

process.on('uncaughtException', function (err) {
  console.error(' Caught exception: ' + err.stack);
});

路由压缩

实际编程中,网络带宽的有效数据负载率是一个值得考虑的问题。对于移动客户端来说,网络资源往往并不丰富,为了尽可能地节省网络资源,往往需要尽大可能地增加数据包的有效数据率。

 类似资料:

相关阅读

相关文章

相关问答