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 中可以启动多个应用并在其中切换,我们没有必要担心降低系统速度或消耗电池电量. 因为系统会自动挂起(有时会终止) ...
随机推荐
- Go学习笔记(一):Ubuntu 环境下Go的安装
本文是根据<Go Web 编程>,逐步学习 Ubuntu 环境下go的安装的笔记. <Go Web 编程>的URL地址如下: https://github.com/astaxi ...
- 浅析 JavaScript 组件编写
之前因项目需要也编写过一些简单的JS组件,大多是基于JQuery库的,一直也没有过总结,导致再次写到的时候还去Google, 近日看到一个文章总结的挺好,拿过整理一下做个备忘. 此次同样是基于jque ...
- 微信分享jssdk config:invalid signature 签名错误
使用微信分享时,按照官方给的demo,使用时一直提示签名错误. 根据微信开发文档(http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd ...
- php开启伪静态(2转)
打开apache的配置文件httpd.conf找到#LoadModule rewrite_module modules/mod_rewrite.so把前面#去掉.没有则添加,但必选独占一行,使apac ...
- No enclosing instance of type test8 is accessible. Must qualify the allocation with an enclosing instance of type test8 (e.g. x.new A() where x is an
在编译一个例子时,结果编译时出现: No enclosing instance of type test8 is accessible. Must qualify the allocation wit ...
- Android SDCard和内部存储中gcc编译后的可执行文件无法运行提示 cannot execute - Permission denied
原因是mount的方式问题,root后运行 su mount -o rw,remount /mnt/sdcard //SDCard mount -o rw,remount /mnt/interna ...
- ubuntu下查看IP Gateway DNS信息
使用nm-tool命令 在最底下有一行: IPv4 Settings: Address: 192.168.0.166 Prefix: (255.255.255.0) Gateway: 192.168. ...
- 【经验】在CSS中定义a:link、a:visited、a:hover、a:active顺序
摘自:http://www.qianyunlai.com/post-2.html 以前用CSS一直没有遇到过这个问题,在最近给一个本科同学做的项目里面.出现一些问题,搜索引擎查了一些网站和资料 ...
- hdu 1245 Saving James Bond
http://acm.hdu.edu.cn/showproblem.php?pid=1245 #include <cstdio> #include <cstring> #inc ...
- 【HDU1166】敌兵布阵(树状数组或线段树)
是一道树状数组的裸题,也可以说是线段树的对于单点维护的裸题.多做这种题目可以提高自己对基础知识的理解程度,很经典. #include <iostream> #include <cst ...