一、运维工具
如上图:可以清楚看到tar框架的运维服务和工具:包括主控Resistry、配置文件中心Config、异常信息Nofify、指标统计Stat、远程log、发布平台Patch、业务信息Property等主要服务,再结合web平台来对这些服务进行可视化操作和运用,对开发和运维人员算是非常方便和人性化了
二、配置中心 config 服务
config服务用于提供整套框架的配置文件保存和读取等操作;后台使用mysql存储
使用例子:
addAppConfig("DBConnection.conf"); //添加应用级别的配置文件
调用TafRemoteConfig::getInstance()->addConfig(filename, result, true)函数:
addConfig函数调用getRemoteFile函数远程从config server获取配置文件信息:
rpc调用:_configPrx->loadConfig(_sApp, (bAppConfigOnly ? "" : _sServerName), sFileName, stream);
跳转到:Config server 的接口函数ConfigImp::loadConfig 函数,如果是应用级别的配置文件:则执行“”select id,config from t_config_files...“” 并且把结果使用string的方式回传给调用者
调用者获取到文件内容,根据文件的名字生成在本地以供后续程序使用文件:std::ofstream out(newFile.c_str());
addConfig(ServerConfig::ServerName + ".conf"); //添加当前进程所在的本地文件
调用:TafRemoteConfig::getInstance()->addConfig(filename, result, false) 注意:最后一个参数bAppConfigOnly设置为false,
调用int ret = _configPrx->loadConfig(_sApp, (bAppConfigOnly ? "" : _sServerName), sFileName, stream); 可见和加载应用级别的配置文件有所不同,这里调用_configPrx服务器的参数,增加了_sServerName。则rpc调用loadConfig接口的时候服务器参数不为空,改掉用loadConfigByHost:同样通过mysql查询t_config_files表格但增加了where查询条件"where server_name = '" + _mysqlConfig.escapeString(appServerName)。至此,实现了从指定服务器拉取配置文件的功能 (这里还关系到引用配置等功能,多个同名文件还涉及到文件合并等,这里先不做详细说明)
三、Nofify服务,官方文档定义为异常信息。输出的信息可以在tars运营平台里面看到
TafRemoteNotify::getInstance()->report("[info]: white list open for ["+ _sUinList + "]");
源码实现:
if(_notifyPrx)
{
if(!bSync)
{
_notifyPrx->async_reportServer(NULL, _sApp + "." + _sServerName, TC_Common::tostr(pthread_self()), sResult);
}
else
{
_notifyPrx->reportServer(_sApp + "." + _sServerName, TC_Common::tostr(pthread_self()), sResult);
}
}
Nofify 服务实现,主要就是把数据插入t_server_notifys_数据库。这里默认都是使用异步的接口,否则估计效率容易有问题,毕竟是直接操作db
string sql;
TC_Mysql::RECORD_DATA rd;
rd["server_name"] = make_pair(TC_Mysql::DB_STR, sServerName);
rd["server_id"] = make_pair(TC_Mysql::DB_STR, sServerName + "_" + current->getIp());
rd["thread_id"] = make_pair(TC_Mysql::DB_STR, sThreadId);
rd["result"] = make_pair(TC_Mysql::DB_STR, sResult);
rd["notifytime"] = make_pair(TC_Mysql::DB_INT, "now()");
string sTable = "t_server_notifys_" + TC_Common::tm2str(TNOW,"%Y%m%d");
try
{
_mysqlConfig.insertRecord(sTable, rd);
四、Stat服务——性能指标统计
服务性能数据采集:调用时间、成功次数、超时次数、异常次数、耗时分布等信息。服务间调用关系链采样。
Stat服务接口:reportProxyMicMsg:udp上报模块间调用采样信息
五、Property —业务指标统计
- 服务业务特性数据采集;支持平均、计数、求和、分布等统计方式
- 服务调用关系链采样
/**
* 上报属性信息
* @param statmsg, 上报信息
* @return int, 返回0表示成功
*/
virtual int reportPropMsg(const map<StatPropMsgHead,StatPropMsgBody>& propMsg, taf::JceCurrentPtr current );
六、Registry ——主控服务:
- 提供对象名称寻址服务,返回IP:Port列表;为客户端提供可用服务列表信息
提供TAF框架核心管理功能 :服务部署、服务起停、服务状态信息查询、发布、配置管理、命令通知
Registry 提供registerNode(node节点注册)、keepAlive(node上报心跳负载)、getServers(获取在该node部署的server列表)、updateServer(更新server状态)、
同时主控提供了AdminRegImp(关联控制接口类),提供如下接口:
getAllApplicationNames(获取application列表)、getAllNodeNames(获取node列表)、shutdownNode(停止 node)、getServerState(获取特定server状态)、startServer(启动特定server)、restartServer( 重启特定server)、notifyServer(通知服务)、patchServer(发布特定server)
例子:startServer接口实现
//更新数据库server的设置状态
_db.updateServerState(application, serverName, nodeName, "setting_state", taf::Active);
判断是否为dns:
DNS: 通过db修改
iRet = _db.updateServerState(application, serverName, nodeName, "present_state", taf::Active);
非DNS:通过node节点启动(下面介绍node节点的作用)
NodePrx nodePrx = _db.getNodePrx(nodeName);
iRet = nodePrx->startServer(application, serverName, result);
七、Node ——服务节点:
- 同一服务器上的服务起停、服务状态信息采集、发布、配置管理、自定义消息通知。
同一服务器上的服务监控,异常退出、僵死等监控重启
node提供的接口:
patch(patch指定服务)、stopAllServers(关闭nodes上所有服务)、
startServer(启动指定服务):
使用sFullExeFileName //默认使用启动脚本路径 stopServer接口也是同理
getState获取指定服务状态:
ServerObjectPtr pServerObjectPtr = ServerFactory::getInstance()->getServer( application, serverName );
if ( pServerObjectPtr )
{
result += "succ";
return pServerObjectPtr->getState();
}
八、patch服务
——统一发布
- 通过web管理所有需要发布的服务和文件的目录
- 提供客户端(patchclient)可以从Patch服务同步文件和目录到远程
- 可以单独使用也可以和node配合使用完成发布动作
listFileInfo(获取路径下所有文件列表信息)、download(下载文件)
九、Taf-Log ——日志中心
日志服务器,用于接收远程日志。业务服务以框架层的api异步发送日志到日志服务器
例子:
#define LOG_STAT(type) FDLOG(type)
其中FDLOG的定义在库文件的taf_logger.h定义如下:
#define FDLOG(x) (TafTimeLogger::getInstance()->logger(x)->any())
TafTimeLogger::getInstance()->logger(x)函数生成并返回:TimeLogger
typedef TC_Logger<TimeWriteT, TC_RollByTime> TimeLogger; TimeLogger的定义如下:
typedef TC_Logger<TimeWriteT, TC_RollByTime> TimeLogger;其中TC_Logger为日志基类模板:模板第一个参数TimeWriteT负责 写Logger.在applicantion服务启动的时候会调用设置远程日志服务器对象的服务:例如log=LogServer.taflog4nmrqsh2.LogObj
TafTimeLogger::getInstance()->setLogInfo(_communicator, ServerConfig::Log, ServerConfig::Application, ServerConfig::ServerName, ServerConfig::LogPath);
这里底层实现函数如下:会获取远程日志服务器的地址
具体写日志的时候,TimeWriteT类重载了operator() ,会调用远程日志服务的logger接口写远程日志,从而实现了日志从本地到远程日志服务器的功能
_logPrx->logger(DYEING_DIR, DYEING_FILE, "day", "%Y%m%d", vDyeingLog);
十、WEB — 管理平台
- 提供服务状态信息查询和起停服务、设置服务日志级别、发送自定义命令等操作页面
- 提供部署服务、自动编译发布、配置管理等运维操作页面
- 提供自动测试操作界面
- 展示服务性能指标数据
- 展示业务特性指标数据