Pomelo 新手周计划(三) Nodejs版

Pomelo 新手周计划(三) Nodejs版

##前言## 今天,我们谈谈Pomelo的会话机制

##会话机制## 从pomelo 的api 文档我们可以发现,有三个大类与session有关

  • LocalSessionService
  • SessionService
  • LocalSession

###Session 介绍### 从pomelo 的api文档中我们可以总结出:

SessionService 是只存在于前端服务器(frontend),session 以每个客户端请求自增1的形式生成 ,用于管理连接 pomelo的客户端,如果在前端服务器不进行相关控制对于每个请求都会产生一个Session,就是说客户端都会在前端的服务器(frontend)里的sessionService产生一个会话,值得注意的是自pomelo0.4.x支持了支持同一账号多处登录,所以seesionService 里面的session 对应的是一个session数组,如果,对session不做任何处理的话,没刷新一次页面,都会对这个session 数组自增 1.从暴露的api,我们可以看出,这个SessionService 可以用于对连接在前端服务器的客户端,踢下线,或者利用session id 直接在前端服务器发消息给客户端。

LocalSessionService 由于SessionService只存在于前端服务器(frontend),如果想在后端服务器(Backend)操作SessionService的话,就需要一个代理类(因为这是两个进程),从源码中可以看到,这个就是从前端服务器复制出来用于backend进行操作的SessionService,主要用于获取踢客户端下线,或者获取相关客户端Session Id。

LocalSession 是用于我们自定义的id 与全局 sessionService进行管理的类。主要用于服务端对客户端之间会话的管理。

从api 文档暴露的接口我们可以得知主要作用:

  • 让我们自定义的id 可以绑定到客户端与服务端之间的会话,用于管理客户端的状态。例如,利用绑定的id实现控制对客户端进行踢掉,监听session的关闭事件。

  • localSession 还提供了一个K/V 的数据存取操作 需要用push或者pushAll 对sessionSerive进行更新。但是,根据官方的回复,不建议把session当做内存库。

###Session FAQ##

  1. Session 是否适合当初内存数据库使用?

session里存的是只读的用户状态数据, 不会同步到数据库。 内存数据的同步是另一个模块实现的。 不要把session当成内存数据库使用, session会在各服务器节点间传递, 因此session的内容越少、越轻量越好。<br/>问题及答案来自于:谁能帮我介绍一下 pomelo的session 用法?

  1. localSessionService和sessionService的区别?

如果看完本章节还是不明白的话?<br/>可以参见有没有文档具体解释localSessionService和sessionService?

  1. 如何在connector以外的服务器中获取全局session?

如何在connector以外的服务器中获取全局session

  1. uid 不能为object

问题来源于 : fail to send message by uid for session not exist

##扩展阅读## ES 5的 bind()方法。

在pomelo的一些demo 里面可能会不理解这么一句话

session.on('closed', onUserLeave.bind(null, this.app));

var onUserLeave = function(app, session) { if(!session || !session.uid) { return; } app.rpc.chat.chatRemote.kick(session, session.uid, app.get(‘serverId’), session.get(‘rid’), null); };

你可能会有这样的疑问

  1. 为什么onUserLeave 会有两个参数?

  2. 函数的bind() 第一个参数null 什么什么意思,结合第一个问题,这里就传了一个参数?那么那个session 还是怎么传过来的?

这个函数 bind() 方法是ES 5 新增的一个特性。用于将函数绑定到某个对象上。

那么这里bind()的方法的作用是什么呢?

要明白这里的bind()的用法,首先我们需要了解一种函数式编程技术—柯里化(currying)

Wiki是这么定义的: 在计算机科学中,柯里化(Currying),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

为了帮助理解这里写一个小例子(来自于Javascript 权威指南第六版 p191)

var sum = function(x, y){
    return x+y;
}
//创建一个类似于sum的新函数,但this的值绑定到null
//并且第一个参数绑定到1, 这个新函数的期望只传入一个实参
var succ = sum.bind(null, 1);

console.log(succ(2)); //输出 3; x 绑定到1,并传入2作为实参

//另外一个做累计计算的函数 var sum2 = function(y ,z){ return this.x + y + z; }

//绑定this 和 y var bindSum2 = sum2.bind({x : 1}, 2); console.log(bindSum2(3)); //输出 6; this.x 绑定到1,y绑定到2, z 绑定到3.

上面这个例子就是柯里化的应用了,现在我们回到pomelo看下,chatpomelo例子里面怎么使用这个柯里化技术。

现在,应该能解决开头的第一个问题了,那么第二个问题,我们需要阅读一下pomelo的源码

阅读源码sessionService.js 464-478

从这十几行代码和柯里化的知识,我们就能够明白为什么onUserLeave为什么会有两个参数了。

var onUserLeave = function(app,  session){

}

最后的参数是通过柯里化的技术把单参数 session 传到我们多参数函数里面。

这里有一篇讲柯里化技术挺有趣的文章: http://www.zhangxinxu.com/wordpress/2013/02/js-currying/

也欢迎到我的博客阅读。。http://blog.gfdsa.net/2013/06/05/pomelo_study_three/


2 回复

前言

今天,我们来深入探讨一下Pomelo中的会话机制。

会话机制

在Pomelo中,有三个主要的类与会话(Session)相关:

  • LocalSessionService
  • SessionService
  • LocalSession

Session 介绍

SessionService

SessionService 主要存在于前端服务器(frontend)。每当客户端发起新的请求时,SessionService 会生成一个新的会话,用于管理这些客户端连接。特别地,从0.4.x版本开始,SessionService 支持同一账号多处登录的功能,因此其内部的会话实际上是一个数组。如果不对这些会话进行管理,每次刷新页面都会导致会话数组的增长。通过SessionService,你可以执行一些基本操作,如踢下线或向特定客户端发送消息。

LocalSessionService

LocalSessionService 作为一个代理类,允许你在后端服务器(Backend)中操作前端服务器上的会话。这种设计是因为前后端通常运行在不同的进程中。

LocalSession

LocalSession 用于将自定义的ID绑定到全局的SessionService。这对于服务端管理和监控客户端状态非常有用,例如通过绑定的ID来控制客户端的踢下线操作或监听会话关闭事件。此外,LocalSession 还提供了键值对(K/V)的数据存储功能,但官方建议不要将其作为内存数据库使用。

Session FAQ

Session 是否适合当内存数据库使用?

Session 中存储的是只读的用户状态数据,不会同步到数据库。内存数据的同步由其他模块负责。因此,不建议将Session用作内存数据库,保持其内容尽可能简单和轻量级是最佳实践。

LocalSessionService 和 SessionService 的区别?

  • SessionService 主要存在于前端服务器,管理所有客户端连接。
  • LocalSessionService 是一个代理类,用于在后端服务器操作前端的Session。

如何在connector以外的服务器中获取全局session?

这需要通过适当的API调用来实现,具体取决于你的应用架构。

uid 不能为object

这个问题可能是因为某些逻辑错误导致无法识别有效的uid。确保uid是字符串或其他简单类型。

扩展阅读

在Pomelo的某些示例代码中,你可能会遇到类似这样的代码片段:

session.on('closed', onUserLeave.bind(null, this.app));

var onUserLeave = function(app, session) {
  if (!session || !session.uid) {
    return;
  }
  app.rpc.chat.chatRemote.kick(session, session.uid, app.get('serverId'), session.get('rid'), null);
};

问题解答

为什么onUserLeave 有两个参数?

这是因为bind() 方法将函数绑定到了特定的对象上,并预设了部分参数。在这个例子中,null 表示不改变函数的this上下文,而this.app则被提前传递给了onUserLeave函数。

函数的bind() 第一个参数null是什么意思?

null 表示不改变函数的this上下文。第二个参数this.app则是提前传递给onUserLeave的参数。

柯里化(Currying)

柯里化是一种函数式编程技术,它将接受多个参数的函数转换为接受一个单一参数的函数,并返回一个新的函数来接受剩余的参数。

例如:

var sum = function(x, y) {
    return x + y;
};

// 创建一个类似于sum的新函数,但this的值绑定到null
// 并且第一个参数绑定到1, 这个新函数的期望只传入一个实参
var succ = sum.bind(null, 1);

console.log(succ(2)); // 输出 3

以上代码展示了柯里化技术的应用。在Pomelo中,通过这种方式可以更好地管理会话和客户端交互。

希望这篇新手周计划对你理解和使用Pomelo的会话机制有所帮助。


在Pomelo框架中,理解会话机制对于开发者来说非常重要。本文将深入探讨Pomelo中的Session概念及其相关类,并通过一些实际的例子来加深理解。

会话机制

Pomelo中的会话主要涉及到三个类:

  • SessionService:它仅存在于前端服务器(frontend)。每当客户端连接时,会自动为该客户端生成一个会话。这对于前端服务器上的连接管理和控制非常有用。需要注意的是,如果你不进行额外处理,每次页面刷新或重新连接时,新的会话会被添加到已有的会话列表中。

  • LocalSessionService:当需要从后端服务器(backend)访问前端的会话信息时,使用LocalSessionService作为中介。它提供了一种跨进程操作会话的方式。

  • LocalSession:允许开发者通过自定义ID来管理客户端和服务端间的会话。这种方式非常适合用来保存客户端的状态信息,如用户是否在线等。

示例代码

下面的示例展示了如何使用SessionService来处理客户端会话。在这个例子中,我们将创建一个简单的会话,并在用户离开时触发一些清理工作。

app.post('/login', function (req, res) {
    var session = req.session; // 获取当前请求的会话
    session.uid = req.body.userId; // 设置用户的唯一标识符
    res.send('登录成功');
});

// 处理会话关闭的事件
app.get('/logout', function (req, res) {
    var session = req.session;
    if (!session || !session.uid) {
        return res.send('未登录');
    }

    session.on('closed', onUserLeave.bind(null, app));
    
    // 强制用户退出
    session.close();
    res.send('退出成功');
});

function onUserLeave(app, session) {
    if (!session || !session.uid) {
        return;
    }
    app.rpc.chat.chatRemote.kick(session, session.uid, app.get('serverId'), session.get('rid'), null);
}

总结

通过上述讨论和示例,你应该对Pomelo中的会话机制有了更深刻的理解。正确使用这些API可以帮助你更好地管理客户端与服务端之间的交互,从而构建出高效稳定的应用。如果你希望深入了解更多细节,建议直接阅读Pomelo的官方文档和源码。

回到顶部