【TARS】RegistryServer中的数据库操作与ReapThread线程

本文详细探讨了TARS框架中RegistryServer的数据库操作类CDbHandle及其静态成员变量的使用,特别是CDbHandle::loadObjectIdCache方法在ReapThread中的应用。ReapThread作为定时任务线程,负责定期更新对象列表和相关缓存,确保服务发现的准确性。CDbHandle类包含多个方法用于服务查找和状态更新,如findObjectById系列方法,同时维护了_objectsCache、_setDivisionCache和_groupPriority等静态成员变量。

0.研究问题的引出

在想要看QueryImp中提供的PRC调用接口的时候,__tars__QueryF_all中提供的方法有:

static ::std::string __tars__QueryF_all[]=
{
                "findObjectById",
                "findObjectById4All",
                "findObjectById4Any",
                "findObjectByIdInSameGroup",
                "findObjectByIdInSameSet",
                "findObjectByIdInSameStation"
};

单单看D:\005-02-代码\016-TARS\TARS\TarsFramework\RegistryServer\QueryImp.cpp代码,对于到静态成员变量

CDbHandle::_objectsCache的值的来源会感到有点疑惑,直到我全局搜索了【loadObjectIdCache】,发现原来

RegistryServer的ReapThread中,在ReapThread::init()和ReapThread::run()的过程中都会调用这个

CDbHandle::loadObjectIdCache这个方法,而这个方法会调用CDbHandle::updateObjectsCache将从数据库中查

询出的结果更新到_objectsCache等静态成员变量中,在此对RegistryServer中的数据库操作与ReapThread线程的

相关内容作出一些研究学习与说明.

1.相关类的说明

1.1 数据库操作类CDbHandle

// 数据库操作类
class CDbHandle
{
private:
    struct GroupPriorityEntry
    {
        std::string        sGroupID;
        std::string        sStation;
        std::set<int>     setGroupID;
    };
    enum GroupUseSelect
    {
        ENUM_USE_WORK_GROUPID,
        ENUM_USE_REAL_GROUPID
    };
    //set中服务的信息
    struct SetServerInfo
    {
        string     sSetId;
        string     sSetArea;
        bool       bActive;
        EndpointF  epf;
    };
    typedef map<string,map<string,vector<CDbHandle::SetServerInfo> > > SetDivisionCache; // <servant,setname,vector>

public:
    CDbHandle(): _enMultiSql(false){} // 构造函数
    int init(TC_Config *pconf);// 初始化
    NodePrx getNodePrx(const string & nodeName);// 获取特定node id的对象代理
    int registerNode(const string & name, const NodeInfo & ni, const LoadInfo & li);// 保存node注册的session
    int destroyNode(const string & name);// 更新node的状态为inactive
    int keepAlive(const string & name, const LoadInfo & li);// 更新node心跳时间及机器负载
    map<string, string> getActiveNodeList(string & result);// 获取活动node列表endpoint信息
    int getNodeVersion(const string &nodeName, string &version, string & result);// 获取node版本
    vector<ServerDescriptor> getServers(const string & app, const string & serverName, const string & nodeName, bool withDnsServer = false);// 获取在该node部署的server列表
    string getProfileTemplate(const string & sTemplateName, string & sResultDesc);// 获取server的配置模板

protected: 
    string getProfileTemplate(const string & sTemplateName, map<string, int> & mapRecursion, string & sResultDesc);// 获取server的配置模板

public:
    // 更新server状态
    int updateServerState(const string & app, const string & serverName, const string & nodeName, const string & stateFields, ServerState state, int processId = -1);
    int updateServerStateBatch(const std::vector<ServerStateInfo> & vecStateInfo);// 批量更新server状态
    vector<EndpointF> findObjectById(const string & id);// 根据id获取对象
    // 根据id获取对象
    int findObjectById4All(const string & id, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp);
    // 根据id获取同组对象
    int findObjectByIdInSameGroup(const string & id, const string & ip, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp, ostringstream &os);
    // 根据id获取优先级序列中的对象
    int findObjectByIdInGroupPriority(const std::string &sID, const std::string &sIP, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
    //根据id和归属地获取全部对象
    int findObjectByIdInSameStation(const std::string &sID, const std::string & sStation, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
    // 根据id和set信息获取全部对象
    int findObjectByIdInSameSet(const string &sID, const vector<string> &vtSetInfo, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
    // 根据setId获取全部对象
    int findObjectByIdInSameSet(const string &sSetId, const vector<SetServerInfo>& vSetServerInfo, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
    vector<string> getAllApplicationNames(string & result);// 获取application列表
    vector<vector<string> > getAllServerIds(string & result);// 获取server列表
    int getConfig(const string &appServerName, const string &fileName, const string &host, string &config, std::string &resultDesc);// 获取合并的配置文件
    int setPatchInfo(const string & app, const string & serverName, const string & nodeName, const string & version, const string & user);// 设置server发布版本
    int setServerTarsVersion(const string & app, const string & serverName, const string & nodeName, const string & version);// 设置server的tars库版本
    int checkNodeTimeout(unsigned uTimeout);// 轮询数据库,将心跳超时的节点及server状态设为不存活
    int checkRegistryTimeout(unsigned uTimeout);// 轮询数据库,将心跳超时的registry设为不存活
    int checkSettingState(const int iCheckLeastChangedTime=3600);// 定时检查在数据库的设置状态为“active”的服务在Node节点上的状态:如果服务在Node的设置状态不是“active”,则通知Node主动重启该服务
    int computeInactiveRate();// 在加载对象列表之前,计算当前非活动状态的node的比率
    int loadObjectIdCache(const bool bRecoverProtect, const int iRecoverProtectRate, const int iLoadTimeInterval=60, const bool bLoadAll=false, bool fromInit = false);// 加载对象列表到内存
    int loadGroupPriority(bool fromInit);// 加载组优先级到内存
    int updateRegistryInfo2Db(bool bRegHeartbeatOff=false);// 更新registry信息到db
    int getNodeTemplateName(const string nodeName, string & sTemplateName);// 获取对应node的模板名称
    int getGroupId(const string& ip);// 根据ip获取组id
    int getGroupIdByName(const string& sGroupName);// 根据组名获取组id
    int loadIPPhysicalGroupInfo(bool fromInit);// 加载IP物理分组信息
    static uint32_t stringIpToInt(const std::string& sip);// ip转换
    static string Ip2Str(uint32_t ip);// ip转换
    static string Ip2StarStr(uint32_t ip);// ip转换

protected:
    vector<EndpointF> getEpsByGroupId(const vector<EndpointF> & vecEps, const GroupUseSelect GroupSelect, int iGroupId, ostringstream &os);// 根据group id获取Endpoint
    vector<EndpointF> getEpsByGroupId(const vector<EndpointF> & vecEps, const GroupUseSelect GroupSelect, const set<int> & setGroupID, ostringstream & os);// 根据group id获取Endpoint
    int doUpdateServerStateBatch(const std::vector<ServerStateInfo> & vecStateInfo, const size_t sizeBegin, const size_t sizeEnd);// updateServerStateBatch的底层实现函数

private:
    void updateStatusCache(const std::map<ServantStatusKey, int>& mStatus,bool updateAll=false);// 更新缓存中的服务状态值
    void updateObjectsCache(const ObjectsCache& objCache,bool updateAll=false);// 更新缓存中的服务信息
    void updateDivisionCache(const SetDivisionCache& setDivisionCache,bool updateAll=false);// 更新缓存中的set信息
    TC_Mysql::MysqlData UnionRecord(TC_Mysql::MysqlData& data1,TC_Mysql::MysqlData& data2);// 对数据库查询结果执行联合操作
    void sendSqlErrorAlarmSMS(const string &err);// 数据库访问异常上报
    void load2GroupMap(const vector<map<string,string> >& serverGroupRule);// 建立ip分组map

protected:
    bool _enMultiSql;//是否允许采用多条语句同时执行方式
    TC_Mysql _mysqlReg;//mysql连接对象
    static map<string , NodePrx> _mapNodePrxCache; //node节点代理列表
    static TC_ThreadLock _NodePrxLock;
    static TC_ReadersWriterData<ObjectsCache>    _objectsCache;//对象列表缓存
    static TC_ReadersWriterData<SetDivisionCache> _setDivisionCache;//set划分缓存
    static TC_ReadersWriterData<std::map<int, GroupPriorityEntry> > _mapGroupPriority;//优先级的序列
    static std::map<ServantStatusKey, int> _mapServantStatus; //servant状态表 
    static TC_ThreadLock _mapServantStatusLock;//存在多线程更新_mapServantStatus,需要加锁   
    static TC_ReadersWriterData<map<string,int> > _groupIdMap;//分组信息
    static TC_ReadersWriterData<map<string,int> > _groupNameMap;
};

1.2  用于执行定时操作的线程类ReapThread

// 用于执行定时操作的线程类
class ReapThread : public TC_Thread, public TC_ThreadLock
{
public:
    ReapThread(); // 构造函数
    ~ReapThread(); // 析构函数
    void terminate(); // 结束线程
    int init(); // 初始化
    virtual void run(); // 轮询函数
protected:
    bool       _terminate; // 线程结束标志
    CDbHandle  _db; // 数据库操作
    int        _loadObjectsInterval1; // 加载对象列表的时间间隔,单位是秒
    int        _leastChangedTime1; // 第一阶段加载时间 consider
    int        _loadObjectsInterval2; //  全量加载时间,单位是秒
    int        _leastChangedTime2; // 
    int        _registryTimeout;// registry心跳超时时间
    bool       _recoverProtect; // 是否启用DB恢复保护功能,默认为打开
    int        _recoverProtectRate;// 启用DB恢复保护功能状态下极限值
    bool       _heartBeatOff;// 主控心跳时间更新开关
};

2.具体分析

2.1 CDbHandle::loadObjectIdCache

CDbHandle::loadObjectIdCache这个函数中更新了
_objectsCache
_mapServantStatus
_setDivisionCache
这三个CDbHandle类的静态成员变量的值.

/**
* 加载对象列表到内存
* @param bRecoverProtect
* @param iRecoverProtectRate
* @param iLoadTimeInterval 加载最近iLoadTimeInterval秒内变化的记录
* @param bLoadAll  是否加载所有服务
* @param bFirstLoad  是否是第一次全量加载
* @param fromInit 是否来着初始化的调用
* @return
*/
 int loadObjectIdCache
(const bool bRecoverProtect, 
 const int iRecoverProtectRate, 
 const int iLoadTimeInterval=60, 
 const bool bLoadAll=false, 
 bool fromInit = false);


int ReapThread::init()
{
...
   _db.loadObjectIdCache(_recoverProtect, _recoverProtectRate,0,true, true);
...
}

int ReapThread::run()
{
  ...
  if(tNow - tLastLoadObjectsStep2 >= _loadObjectsInterval2)
  {
     tLastLoadObjectsStep2 = tNow;
     //全量加载,_leastChangedTime2参数没有意义
     _db.loadObjectIdCache(_recoverProtect, _recoverProtectRate,_leastChangedTime2,true, false);
   }
   else
   {
       _db.loadObjectIdCache(_recoverProtect, _recoverProtectRate,_leastChangedTime1,false, false);
   }
  ...
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值