pomelo源码分析--session

作者:shihuaping0918@163.com,转载请注明作者

pomelo中有session/frontendSession/backendSession/sessionService。名字看起来都有点像,这一篇准备讲session和sessionService。session是对用户连接的一个抽象,它会调用sessionService。sessionService是session的具体实现底层。session只在frontend服务器中存在。如果还有印象的话,应该能记得gate负责接受外部连接,做frontend的负载均衡,将连接分派到不同的frontend上。connector再做路由处理,转到不同的backend服务器上,也就是逻辑服务器。

在分析session.js前要先分析sessionService.js,因为session实际是抽象了sessionService。从底向上更容易理解。

sessionService.js,先看一下Session的定义,Session中有一个id,uid,还有一个frontendId,还有一个socket。id就是sid,uid就是用户id,socket就是连接对应的socket。ftontendId就是frontend服务器id。sid和uid分别是从哪里来的呢?

/**
 * Session maintains the relationship between client connection and user information.
 * There is a session associated with each client connection. And it should bind to a
 * user id after the client passes the identification.
 *
 * Session is created in frontend server and should not be accessed in handler.
 * There is a proxy class called BackendSession in backend servers and FrontendSession 
 * in frontend servers.
 */
var Session = function(sid, frontendId, socket, service) {
  EventEmitter.call(this);
  this.id = sid;          // r
  this.frontendId = frontendId; // r
  this.uid = null;        // r 注意这里,uid初始是null
  this.settings = {};

  // private
  this.__socket__ = socket;
  this.__sessionService__ = service;
  this.__state__ = ST_INITED;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sid实际上是socket创建时指定的一个id。sid = socket.id;,它是在connector中生成的,对于sioconnector,有这样一段代码。

var curId = 1;

  sio.on('connection', function (socket) {
    var siosocket = new SioSocket(curId++, socket); //curId++就是sid
    self.emit('connection', siosocket);
    siosocket.on('closing', function(reason) {
      siosocket.send({route: 'onKick', reason: reason});
    });
  });
1
2
3
4
5
6
7
8
9
所以这个sid是connector内部维护的,在服务生命周期内自增的一个ID。uid这这个时候是null,没有赋值的。 
connector.js

  session.on('bind', function(uid) {
    logger.debug('session on [%s] bind with uid: %s', self.app.serverId, uid);
    // update connection statistics if necessary
    if (self.connection) {
      self.connection.addLoginedUser(uid, {
        loginTime: Date.now(),
        uid: uid,
        address: socket.remoteAddress.ip + ':' + socket.remoteAddress.port
      });
    }
    self.app.event.emit(events.BIND_SESSION, session);
  });
1
2
3
4
5
6
7
8
9
10
11
12
connectorService.js

Session.prototype.bind = function(uid) {
  this.uid = uid;
  this.emit('bind', uid);
};
1
2
3
4
5
uid是在bind事件发生时出现的。这个bind被调用的时候,把uid给赋进去了。注意是sessionService里的Session.on(‘bind’…)。pomelo把这个session的名字复用了太多次。有点混乱。

为了避免概念上的混乱,下面总结一下,先说明一下session是指对客户端连接的一个抽象,它里面包含uid,sid,socket,以后出现session这单个单词,就是指连接的抽象。pomelo核心中有一个session component,这个session component是对sessionService的抽象。sessionService位于service下,实现session管理的具体工作。session的具体结构是在sessionService中出现的,叫Session。很绕啊,这就是名字取得不好的弊端。

下面再来看一下session component和sessionService之间是什么样的关系。

var SessionService = require('../common/service/sessionService');

module.exports = function(app, opts) {
  var cmp = new Component(app, opts);
  app.set('sessionService', cmp, true);
  return cmp;
};

/**
 * Session component. Manage sessions.
 *
 * @param {Object} app  current application context
 * @param {Object} opts attach parameters
 */
var Component = function(app, opts) {
  opts = opts || {};
  this.app = app;
  this.service = new SessionService(opts); //创建sessionService
 //这段话结尾有个(),代表函数调用
  var getFun = function(m) {
    return (function() {
          return function() {
            return self.service[m].apply(self.service, arguments); //arguments是随调用变化的
          };
    })();
  };
  // proxy the service methods except the lifecycle interfaces of component
  var method, self = this;
  for(var m in this.service) { //遍历sessionService的成员
    if(m !== 'start' && m !== 'stop') { //如果不是start和stop方法
      method = this.service[m]; //取出成员
      if(typeof method === 'function') { //如果成员是函数
        this[m] = getFun(m); //把函数加到自己模块里
      }
    }
  }
};

Component.prototype.name = '__session__';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
根据上面的分析,session component实际上是对sessionService做了一层代理。把sessionService的函数都加载到sesssion component里来了。这个代理的实现,下一篇文章会专门去讲它。
--------------------- 
作者:心中那自由的世界 
来源:CSDN 
原文:https://blog.csdn.net/119365374/article/details/77622494 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值