• 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。

    image

      我们在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类型。

    image

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

    image

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

    image

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

    image

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

    image

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

    image

      完整的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;
        }
    };
  • 相关阅读:
    剑指Offer面试题:6.用两个栈实现队列
    四类范式
    Programming Paradigms, Interactive Mind Map Software
    Programming paradigms
    Hierarchy and examples of programming languages grouped by concepts --编程语言分类
    web.xml是tomcat和spring间的桥梁,是tomcat构建spring运行环境的说明书
    tomcat加载web.xml的过程---StandardContext、ContextConfig源码分析
    spring context的层次关系
    spring的context---ServletContext WebApplicationContext---Spring各种上下文的关系详解
    Context hierarchy in Spring Web MVC
  • 原文地址:https://www.cnblogs.com/moyangvip/p/5058397.html
Copyright © 2020-2023  润新知