6、Khala的登录生命周期管理
khala能够对设备进行生命周期管理,并提供了与生命周期相关的接口,用户只需在具体的设备类型实现类中重写这些生命周期接口,即可享受khala对于生命周期管理的同时定制与业务相关的操作。具体接口解释如下:
onLoginCheckMsg():
进行登录检查,在此可以通过查询DB等方式检查登录设备账号是否合法,可以为连接设备设置设备ID(此ID必须唯一,将被视为设备key,若出现重复将执行onLoginFailureMsg,若未设置将以临时ID值作为ID key),若账号检查失败,设置失败回复消息并直接返回false即可。若检查成功,并且设置的ID未重复,将完成登录操作并执行onLoginSuccessMsg。
onLoginSuccessMsg():
登录成功,在此可以执行登录成功后的相关操作。此时设备进入登录设备的生命周期。
onLoginFailureMsg():
登录异常,设置ID与已登录的设备ID冲突,一般表明该账号已登录。
onLogoutMsg():
注销操作,表明该账号退出登录。此操作结束后,将执行releaseConnNode释放该设备的相关资源,并结束该设备的登录生命周期,并最终断开连接。
releaseConnNode():
释放设备资源。将在退出设备生命周期时被执行,一般在设备执行注销操作后执行,但在设备异常退出的时候,也会执行该操作。

我们通过建立一个MyUsrType的设备类型为来体验khala的设备生命周期。MyUsrType通过继承于NodeType享受登录设备管理,并对相关的生命周期接口进行重写定制。
我们在mysql中建立名为UsrInfo的表,用来记录设备账号信息。在此我们新建了两个账号,分别为moss1和moss2,且我们通过DB维护了每个账号的不同id。

我们在onLoginCheckMsg中对登录账号信息查询DB进行检查。具体的DB操作我们可以通过封装mysql++实现,具体相关可百度mysql++文档。若该账号不存在,我们回复登录失败的消息,并返回false,即结束了此次登录请求操作。若该账号存在,我们将DB中保存的ID作为设备ID。并返回true。
virtual bool onLoginCheckMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
//获取账号名
std::string name = msg[KEY_LOGIN_NAME].asString();
//获取密码
std::string passwd = msg[KEY_PASSWD].asString();
//查询DB
UsrInfoResult res = UsrInfoDao::getInstance().queryUsrInfo(name,passwd);
if (!res.isSuccess()) {
//该账号不存在
infoNodePtr->send("login failure,err account!");
return false;
}
//获取DB查询信息
UsrInfoDo usrInfoDo = res.getUsrInfoDo();
//将设备ID设置为DB中保存的ID
infoNodePtr->setId(usrInfoDo.id);
return true;
}
之后系统将会以该ID做为key对已登录设备进行检查,若该ID在已登录设备中存在,则表明该账号已经登录,将执行onLoginFailureMsg操作。此处我们实现的onLoginFailureMsg操作很简单,仅仅只是告诉客户端该ID所对应的设备账号已经登录,此次登录失败。
virtual bool onLoginFailureMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
infoNodePtr->send("login failure,logined id!");
return true;
}
若该ID未登录,则会执行相应的登录操作,将该连接信息保存到登录设备池等。并最后执行onLoginSuccessMsg,表明该设备账号登录成功,正式进入登录生命周期中。我们可以在此实现登录成功后的相关操作。我们在此的实现也很简单,告诉客户端此次登录成功,且设备的ID为多少。
virtual bool onLoginSuccessMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
std::stringstream ss;
ss << "login success! your id is:" << infoNodePtr->getId();
infoNodePtr->send(ss.str());
return true;
}
至于注销操作,依旧只需实现具体的和业务相关的消息返回就行,Khala系统收到注销操作后,将会自行处理之前维护的设备信息,将其释放并调用releaseConnNode释放设备申请的相关资源,最后结束此次登录的生命周期并断开连接。
virtual bool onLogoutMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
khala::Timestamp time) {
std::stringstream ss;
ss << "logout success! your id is:" << infoNodePtr->getId();
infoNodePtr->send(ss.str());
return true;
}
因为此次设备并未主动申请相关资源,因此releaseConnNode操作无需进行任何操作,但为了展示releaseConnNode在设备登录生命周期的时机,我们通过系统日志进行相关输出。
virtual void releaseConnNode(khala::InfoNodePtr& infoNodePtr,
khala::Timestamp time) {
LOG_INFO << "this is node id:" << infoNodePtr->getId()<< " release function!";
}
最后,我们还要为我们的MyUsrType设置类型名,同时在main中进行注册操作,此处不谈。
MyUsrType的完整代码见最后。
我们通过客户端进行测试(./example/testClient/HelloKhalaClient3.py)。
我们选择登录操作,并且选择登录类型为usrType,然后输入moss1的账号密码,此时显示我们登录成功,且id为1,正是DB中moss1对应的ID。我们再查询isLogin命令,显示我们已经登录。查询devType,正是我们新创建的MyUsrType类型。

如果我们输入一个错误的账号密码,结果返回错误的账号,且查询isLogin显示未登录。

此时我们的moss1账号已经登录,如果我们再开启一个客户端,通过moss1账号进行登录操作。此时返回onLoginFailureMsg中的处理,即该账号已经在别处登录,此次登录失败。

我们再在已经登录的moss1账号上进行注销操作。我们收到正确的注销操作返回,连接被断开。

此时我们查询khala服务端日志,显示releaseConnNode被成功执行。

我们再次开启客户端,并用moss1账号登录,再通过ctr+c强制客户端退出,此时我们再检查日志,显示系统检测到客户端异常退出,同时releaseConnNode依旧得到了执行。因此如果我们在登录连接中申请了相关资源,不管客户端最后是正确被注销退出还是异常情况下退出,只要我们在releaseConnNode中执行了正确的申请资源释放操作,都不会导致服务端因为资源泄露而出错。

完整的MyUsrType类代码:
#include <khala/NodeType.h>
#include <sstream>
#include"DAO/UsrInfoDao.h"
class MyUsrType: public khala::NodeType {
public:
MyUsrType();
virtual ~MyUsrType();
virtual bool onLoginCheckMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
std::string name = msg[KEY_LOGIN_NAME].asString();
std::string passwd = msg[KEY_PASSWD].asString();
UsrInfoResult res = UsrInfoDao::getInstance().queryUsrInfo(name,
passwd);
if (!res.isSuccess()) {
infoNodePtr->send("login failure,err account!");
return false;
}
UsrInfoDo usrInfoDo = res.getUsrInfoDo();
infoNodePtr->setId(usrInfoDo.id);
return true;
}
virtual bool onLoginSuccessMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
std::stringstream ss;
ss << "login success! your id is:" << infoNodePtr->getId();
infoNodePtr->send(ss.str());
return true;
}
virtual bool onLoginFailureMsg(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
infoNodePtr->send("login failure,logined id!");
return true;
}
virtual bool onLogoutMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
khala::Timestamp time) {
std::stringstream ss;
ss << "logout success! your id is:" << infoNodePtr->getId();
infoNodePtr->send(ss.str());
return true;
}
virtual void releaseConnNode(khala::InfoNodePtr& infoNodePtr,
khala::Timestamp time) {
LOG_INFO << "this is node id:" << infoNodePtr->getId()
<< " release function!";
}
virtual const std::string& getObjectTypeName() {
static std::string typeStr(MY_USR_TYPE);
return typeStr;
}
};
6、Khala的登录生命周期管理的更多相关文章
- Salesforce 应用生命周期管理
应用程序生命周期管理 一个Salesforce系统可以有多个版本,最常见的有: production版本:终端用户实际使用的版本 sandbox版本:沙盒环境,用于开发.测试等 在对Salesforc ...
- 4-K8S 部署Java应用及应用程序生命周期管理
1.在kubernetes中部署应用程序流程 准备项目源码-->编译构建-->产出war包,打包到镜像中-->推送到镜像仓库 获取源代码是开发人员提交代码的代码托管地址,有Git.S ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- 【转】Tomcat组件生命周期管理
Tomcat组件生命周期管理 Tomcat中Server,Service,Connector,Engine,Host,Context,它们都实现了org.apache.catalina.Lifecyc ...
- Castle IOC容器组件生命周期管理
主要内容 1.生命处理方式 2.自定义生命处理方式 3.生命周期处理 一.生命处理方式 我们通常创建一个组件的实例使用new关键字,这样每次创建出来的都是一个新的实例,如果想要组件只有一个实例,我们会 ...
- Java实现生命周期管理机制
先扯再说 最近一直在研究某个国产开源的MySQL数据库中间件,拉下其最新版的代码到eclipse后,启动起来,然后做各种测试和代码追踪:用完想要关闭它时,拉出它的STOP类想要运行时,发现这个类里赫然 ...
- 依赖注入及AOP简述(十一)——生命周期管理 .
2. 生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被 ...
- Windows 8 动手实验系列教程 实验5:进程生命周期管理
动手实验 实验5:进程生命周期管理 2012年9月 简介 进程生命周期管理对构建Windows应用商店应用的开发者来说是需要理解的最重要的概念之一.不同于传统的Windows应用(它们即使在后台仍然继 ...
- 快速构建Windows 8风格应用30-应用生命周期管理
原文:快速构建Windows 8风格应用30-应用生命周期管理 引言 Windows 8 中可以启动多个应用并在其中切换,我们没有必要担心降低系统速度或消耗电池电量. 因为系统会自动挂起(有时会终止) ...
随机推荐
- Json部分知识(前台显示格式、Json-lib日期处理)
1,Json格式用于datagrid数据显示 easyui前台显示数据可以使用JSONObject,也可以使用JSONArray.但是如果需要在datagrid表格中进行数据显示,只能使用JSONOb ...
- a标签加绝对定位在图片上面,a的链接和块状属性block失效,而且是所有IE版本都失效的
谷歌和火狐浏览器下测试是正常的,IE下鼠标移过logo是没有超链接的提示的 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...
- js修改window对象中的url历史记录
//页面地址:http://localhost/11/account.html//访问页面后,地址变为:http://localhost/11/account.html?type=banana con ...
- Ecshop导航栏标题栏的伪静态设置
当Ecshop的伪静设置成功之后,左侧的分类标签,包括具体的产品页面都可以顺利的打开伪静态页面,但是点击导航栏,或者标题栏的时候,却还是之前的数据库标签页的方式,这是怎么一回事呢? 这是由于,Ecsh ...
- Python基础第五天
双层装饰器 字符串格式化 Python字符串格式有2种方式:百分号方式.format方式:建议使用format方式 1.百分号方式 格式:%[(name)][flags][width].[precis ...
- Asset Catalog Creator Free 生成程序内图标的软件
Asset Catalog Creator Free 生成程序内图标的软件
- iOS 6分享列表——UIActivityViewController详解
iOS 6分享列表——UIActivityViewController详解 2013-06-03 01:42:33 发表评论 在iOS 6之后提供了一个分享列表视图,它通过UIActivity ...
- 记事本创建servlet在tomcat中发布基本思路
在webapps中新建文件夹H,在其中再创建WEB-INF文件夹,在创建classes文件夹和web.xml文件,web.xml需要配置一下,classes文件夹中存放Servlet经编译过的clas ...
- position: absolute;绝对定位水平居中问题
position: absolute;绝对定位水平居中问题 用CSS让元素居中显示并不是件很简单的事情—同样的合法CSS居中设置在不同浏览器中的表现行为却各有千秋.让我们先来看一下CSS中常见的几种让 ...
- ZOJ 3188 ZOJ 3188 Treeland Exhibition(树形DP)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3278 题意:给出一棵树,找出一个不大于长度为m的链,使得其他点到该链 ...