CAT配置
在CAT中,有非常多的配置去指導監控的行為,每個配置都有相應的配置管理類來管理,都有一個配置名, 配置在數據庫或者配置文件中都是以xml格式存儲,在運行時會被解析到具體實體類存儲。我們選取一個配置的初始化代碼來分析:

public class ServerFilterConfigManager implements Initializable { @Inject protected ConfigDao m_configDao; private volatile ServerFilterConfig m_config; private static final String CONFIG_NAME = "serverFilter"; @Override public void initialize() throws InitializationException { try { Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); } catch (DalNotFoundException e) { try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); config.setName(CONFIG_NAME); config.setContent(content); m_configDao.insert(config); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); } catch (Exception ex) { Cat.logError(ex); } } catch (Exception e) { Cat.logError(e); } if (m_config == null) { m_config = new ServerFilterConfig(); } Threads.forGroup("cat").start(new ConfigReloadTask()); } }
以上代碼是serverFilter配置的初始化邏輯,該配置的管理類是ServerFilterConfigManager,可以看到他實現了Initializable接口,所以,在ServerFilterConfigManager被plexus容器實例化之后,就會調用initialize()做一些初始化的工作,咱們看看他的初始化邏輯。
1、他首先讀取cat數據庫的config表,如果根據配置名 CONFIG_NAME 找到相關的配置信息。
2、如果 config 表中存在配置信息,則通過 DefaultSaxParser.parse(content) 方法解析xml配置信息,並將解析后的配置信息寫入實體對象ServerFilterConfig m_config,我們的xml配置文件必須遵守CAT的解析規則,他們才會被正確的解析成對應的XxxConfig對象,具體配置規則大家在有需要的時候一步步摸索。
3、如果 config 表中不存在配置信息,就會去讀取默認 xml 文件, 解析后寫入到數據庫和實體對象,下次再初始化的時候就是直接從數據庫讀取了,xml一般存在於cat-core/src/main/resources/config/ 和 cat-home/src/main/resources/config/ 兩個目錄。
4、其中有兩個配置 serverFilter 和 aggreationConfig, 開啟了檢查更新線程,線程每隔1分鍾檢查配置是否更新,有更新就重新加載配置。
5、server.xml 配置文件的目錄是由環境變量 CAT_HOME指定的,由CatHomeModule在setup安裝的時候初始化。
我們來列一列cat有哪些配置
配置名 | 配置管理類 | 實體類 | 配置文件cat-xxxx/src/main/resources/config/*.xml | 用途 |
ServerConfigManager | ServerConfigManager | ServerConfig | 環境變量 CAT_HOME/server.xml | 未知 |
serverFilter | ServerFilterConfigManager | ServerFilterConfig | cat-core/..../serverFilter.xml | 未知 |
all-report-config | AllReportConfigManager | AllConfig | cat-home/..../all-report-config.xml | 未知 |
metricProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../metricProductLine.xml | 未知 |
userProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../userProductLine.xml | 未知 |
applicationProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../applicationProductLine.xml | 未知 |
networkProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../networkProductLine.xml | 未知 |
systemProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../systemProductLine.xml | 未知 |
databaseProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../databaseProductLine.xml | 未知 |
cdnProductLine | ProductLineConfigManager | ProductLineConfig | cat-home/..../cdnProductLine.xml | 未知 |
metricConfig | MetricConfigManager | MetricConfig | cat-home/..../metricConfig.xml | 未知 |
blackList | BlackListManager | BlackList | cat-home/..../blackList.xml | 未知 |
routerConfig | RouterConfigManager | RouterConfig | cat-home/..../routerConfig.xml | 未知 |
domainGroup | DomainGroupConfigManager | DomainGroup | cat-home/..../domainGroup.xml | 未知 |
heartbeat-display-policy | HeartbeatDisplayPolicyManager | HeartbeatDisplayPolicy | cat-home/..../heartbeat-display-policy.xml | 未知 |
topologyConfig | TopologyGraphConfigManager | TopologyGraphConfig | cat-home/..../topologyConfig.xml | 未知 |
topoGraphFormat | TopoGraphFormatConfigManager | TopoGraphFormatConfig | cat-home/..../topoGraphFormat.xml | 未知 |
bugConfig | BugConfigManager | BugConfig | cat-home/..../bugConfig.xml | 未知 |
senderConfig | SenderConfigManager | SenderConfig | cat-home/..../senderConfig.xml | 未知 |
netGraphConfig | NetGraphConfigManager | NetGraphSet | cat-home/..../netGraphConfig.xml | 未知 |
url-pattern | UrlPatternConfigManager | UrlPattern | cat-home/..../url-pattern.xml | 未知 |
app-config | AppConfigManager | AppConfig | cat-home/..../appConfig.xml | 未知 |
app-speed-config | AppSpeedConfigManager | AppSpeedConfig | cat-home/..../app-speed-config.xml | 未知 |
appRule | AppRuleConfigManager | MonitorRules | cat-home/..../appRule.xml | 未知 |
storageGroup | StorageGroupConfigManager | StorageGroupConfig | cat-home/..../storageGroup.xml | 未知 |
activityConfig | ActivityConfigManager | ActivityConfig | cat-home/..../activityConfig.xml | 未知 |
exceptionRuleConfig | ExceptionRuleConfigManager | ExceptionRuleConfig | cat-home/..../exceptionRuleConfig.xml | 未知 |
thirdPartyConfig | ThirdPartyConfigManager | ThirdPartyConfig | cat-home/..../thirdPartyConfig.xml | 未知 |
aggreationConfig | AggregationConfigManager | Aggregation | cat-home/..../aggreationConfig.xml | 未知 |
webRule | WebRuleConfigManager | MonitorRules | cat-home/..../webRule.xml | 未知 |
businessRuleConfig | BusinessRuleConfigManager | MonitorRules | cat-home/..../businessRuleConfig.xml | 未知 |
networkRuleConfig | NetworkRuleConfigManager | MonitorRules | cat-home/..../networkRuleConfig.xml | 未知 |
databaseRuleConfig | DatabaseRuleConfigManager | MonitorRules | cat-home/..../databaseRuleConfig.xml | 未知 |
systemRuleConfig | SystemRuleConfigManager | MonitorRules | cat-home/..../systemRuleConfig.xml | 未知 |
heartbeatRuleConfig | HeartbeatRuleConfigManager | MonitorRules | cat-home/..../heartbeatRuleConfig.xml | 未知 |
appComparisonConfig | AppComparisonConfigManager | AppComparisonConfig | cat-home/..../appComparisonConfig.xml | 未知 |
app-command-format-config | CommandFormatConfigManager | CommandFormat | cat-home/..../app-command-format-config.xml | 未知 |
alertConfig | AlertConfigManager | AlertConfig | cat-home/..../alertconfig.xml | 未知 |
alertPolicy | AlertPolicyManager | AlertPolicy | cat-home/..../alertPolicy.xml | 未知 |
transactionRule | TransactionRuleConfigManager | MonitorRules | cat-home/..../transactionRule.xml | 未知 |
eventRule | EventRuleConfigManager | MonitorRules | cat-home/..../eventRule.xml | 未知 |
storageSQLRule | StorageRuleConfigManager | MonitorRules | cat-home/..../storageSQLRule.xml | 未知 |
storageCacheRule | StorageRuleConfigManager | MonitorRules | cat-home/..../storageCacheRule.xml | 未知 |
代碼自動生成
上一節 ServerFilterConfigManager 類代碼中的配置實體ServerFilterConfig的定義為 public class ServerFilterConfig extends BaseEntity<ServerFilterConfig>,所有的實體類都繼承自BaseEntity<T>,這些實體類代碼不是自己寫的,而是通過插件生成的,插件在cat-home/pom.xml,cat-core/pom.xml,cat-consumer/pom.xml 中都會有定義,用以添加需要的實體,包括后面數據庫的操作相關的實體,也是通過類似方式生成,這有點類似mybatis的數據庫表對象生成器generator,我們來看看cat-core中的一個插件的定義:

<plugins> <plugin> <groupId>org.unidal.maven.plugins</groupId> <artifactId>codegen-maven-plugin</artifactId> <executions> <execution> <id>generate data model</id> <phase>generate-sources</phase> <goals> <goal>dal-model</goal> </goals> <configuration> <manifest>${basedir}/src/main/resources/META-INF/dal/model/server-manifest.xml, ${basedir}/src/main/resources/META-INF/dal/model/command-format-manifest.xml, ... ${basedir}/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml, </manifest> </configuration> </execution> <execution> <id>generate dal jdbc model</id> <phase>generate-sources</phase> <goals> <goal>dal-jdbc</goal> </goals> <configuration> <manifest>${basedir}/src/main/resources/META-INF/dal/jdbc/report-manifest.xml, ${basedir}/src/main/resources/META-INF/dal/jdbc/config-manifest.xml, ${basedir}/src/main/resources/META-INF/dal/jdbc/app-manifest.xml, <![CDATA[, ${basedir}/src/main/resources/META-INF/dal/jdbc/report-manifest.xml, ${basedir}/src/main/resources/META-INF/dal/jdbc/config-manifest.xml, ,]]></manifest> </configuration> </execution> </executions> </plugin> <plugins>
插件在pom.xml中定義后,會在Maven Projects功能中展現出來,如圖5:
插件會根據xml中的描述,生成相應的類,比如 ServiceFilterConfig實體類的描述文檔為: ${basedir}/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml,這個文檔是個父文檔,它將引入文檔server-filter-config-codegen.xml和server-filter-config-model.xml,這兩個文檔有對將要生成的類的成員變量、成員函數的描述。
在下一章節的消息分析器中,和報表相關的非常多的實體類 EventReport、EventType、EventName、TransactionReport、TransactionType、TransactionName、Machine等等,都是由CAT代碼生成插件根據配置 cat-sonsumer/src/main/resources/META-INFO/dal/model/*.xml 自動生成的,我們可以通過修改xml文件為我們的報表添加新的成員變量。
數據庫操作
在上一節插件中,還有一個是與數據庫操作相關類的生成有關的,比如上邊config表相關數據庫操作類的描述文檔為${basedir}/src/main/resources/META-INF/dal/jdbc/config-manifest.xml,插件會根據xml文檔生成Config、ConfigDao、ConfigEntity三個類放在下圖目錄中:
那么config表有什么作用呢?這三個類分別有什么用途?在上一節我們多次用到這張表,例如我們初始化配置的時候,讀取config表的記錄,如果沒有初始數據的話,配置管理類會從xml讀取配置信息並插入config表了。
現在我們來講一講cat的數據庫操作,先看看數據庫操作的類圖:
對數據庫表的操作位於Dao類中,比如Config表的操作類就是 ConfigDao,所有Dao繼承自AbstractDao,每個Dao都會擁有數據庫執行引擎(QueryEngine)的指針,用以執行所有的SQL語句,QueryEngine在Dao初始化函數initialize()中被實例化,
每個執行引擎QueryEngine都擁有實體信息管理(EntityInfoManager),以及查詢解析器(QueryResolver),查詢執行器(QueryExecutor),事務管理器(TransactionManager),
實體信息管理類(EntityInfoManager)管理每個表的Entity信息,Entity中描述對數據庫的具體操作,Config表的實體對象就是ConfigEntity,他會在AbstractDao.initialize()函數中向EntityInfoManager注冊。
另外還有一個關鍵的類,就是Config類,繼承自DataObject,是對config表的所有字段的描述。
我們來看幾個數據庫操作的案例,下面源碼,

public class ConfigDao extends AbstractDao { public List<Config> findAllConfig(Readset<Config> readset) throws DalException { Config proto = new Config(); List<Config> result = getQueryEngine().queryMultiple( ConfigEntity.FIND_ALL_CONFIG, proto, readset); return result; } public Config findByName(String name, Readset<Config> readset) throws DalException { Config proto = new Config(); proto.setName(name); Config result = getQueryEngine().querySingle( ConfigEntity.FIND_BY_NAME, proto, readset); return result; } public int insert(Config proto) throws DalException { return getQueryEngine().insertSingle( ConfigEntity.INSERT, proto); } @Override protected Class<?>[] getEntityClasses() { return new Class<?>[] { ConfigEntity.class }; } }
函數功能:
1、findAllConfig函數是獲取所有的配置,返回的對象,是Config的List列表,調用查詢引擎QueryEngine的queryMultiple 查詢多條記錄方法,傳入的參數分別是實體操作方法ConfigEntity.FIND_ALL_CONFIG、查詢條件數據proto、readset。
2、findByName函數則是按名字查詢Config配置,邏輯跟上一個類似。
3、insert函數是插入一條config記錄,調用查詢引擎的insertSingle方法,參數分別是實體方法ConfigEntity.INSERT, 插入數據 proto。
4、getEntityClasses函數獲取實體類
接下來我們以查詢單條記錄作為例子來看看查詢引擎的實現邏輯,如下源碼:

public class DefaultQueryEngine extends ContainerHolder implements QueryEngine { public <T extends DataObject> T querySingle(QueryDef query, T proto, Readset<?> readset) throws DalException { QueryContext ctx = this.createContext(query, proto); ctx.setReadset(readset); ctx.setFetchSize(1); this.m_queryResolver.resolve(ctx); List<T> results = this.m_queryExecutor.executeQuery(ctx); if(results.isEmpty()) { throw new DalNotFoundException("No record has been found for " + proto); } else { return (DataObject)results.get(0); } } protected <T extends DataObject> QueryContext createContext(QueryDef query, T proto) { QueryContext ctx = new DefaultQueryContext(); EntityInfo enityInfo = this.m_entityManager.getEntityInfo(query.getEntityClass()); Map<String, Object> queryHints = this.getQueryHints(query, proto); ctx.setQuery(query); ctx.setProto(proto); ctx.setEntityInfo(enityInfo); ctx.setQueryHints(queryHints); return ctx; } }
1、數據庫引擎首先為該查詢和對應條件數據proto創建查詢上下文(QueryContext),
2、然后會設置readset,並設置查詢條數為1條,
3、然后將上下文交給查詢解析器(QueryResolver),解析器會根據查詢上下文解析成對應的sql狀態語,復制到上下文的 m_sqlStatement字段
4、最后將上下文交給執行器QueryExecutor去執行。並返回結果,如果沒有找到結果,引擎會拋出DalNotFoundException異常。
數據庫連接管理
數據庫記錄的更新與插入最終會由 MysqlWriteHandler 執行,而查詢則由 MysqlReadHandler執行,兩個Handler都會通過TransactionManager 的 getConnection 函數獲取數據庫的連接。
數據庫連接是由DataSource管理,DataSource是由數據源管理器(DataSourceManager)管理,TransactionManager 擁有DataSourceManager的指針,DataSourceManager 提供函數getDataSource(String name)獲取DataSource對象;
getDataSource函數首先會從DataSourceManager 自身 m_dataSources 中尋找指定數據源,如果沒有找到,再從數據源描述管理器(JdbcDataSourceDescriptorManager) 中獲取數據庫數據源描述信息(JdbcDataSourceDescriptor),然后利用描述信息去初始化連接池。
描述管理器也是先從自身 m_descriptors 中看是否存在指定描述信息(JdbcDataSourceDescriptor),如果沒有,則會通過 DataSourceProviver 生成描述信息。
DataSourceProviver可以認為是初始數據源描述信息(JdbcDataSourceDescriptor)的提供者,JdbcDataSourceDescriptorManager初始化的時候,Plexus容器會基於xml文檔實例化 DataSourceProviver,這些xml文檔有 cat-home/....../META-INF/plexus/components-cat-home.xml,cat-consumer/....../META-INF/plexus/components-cat-consumer.xml, cat-core/....../META-INF/plexus/components-cat-core.xml, 文檔中的 datasourceFile 就是數據源配置路徑,例如下面xml文檔:

component> <role>org.unidal.dal.jdbc.datasource.DataSourceProvider</role> <implementation>org.unidal.dal.jdbc.datasource.DefaultDataSourceProvider</implementation> <configuration> <datasourceFile>/data/appdatas/cat/datasources.xml</datasourceFile> </configuration> </component>
JdbcDataSourceDescriptorManager是如何通過DataSourceProviver獲取數據源描述信息(JdbcDataSourceDescriptor)?實際上是通過DataSourceProviver讀取並解析datasourceFile文件,例如上面的/data/appdatas/cat/datasources.xml,然后將解析后的數據寫入 DataSourceDef 對象,然后JdbcDataSourceDescriptorManager調用 buildDescriptor(DataSourceDef ds) 創建描述信息,下面是buildDescriptor的源碼:

public class JdbcDataSourceDescriptorManager extends ContainerHolder implements Initializable { private Map<String, JdbcDataSourceDescriptor> m_descriptors = new HashMap(); private List<DataSourceProvider> m_providers; private String m_datasourceFile; protected JdbcDataSourceDescriptor buildDescriptor(DataSourceDef ds) { JdbcDataSourceDescriptor d = new JdbcDataSourceDescriptor(); PropertiesDef properties = ds.getProperties(); String url = properties.getUrl(); String connectionProperties = properties.getConnectionProperties(); if(connectionProperties != null && connectionProperties.length() > 0) { d.setProperty("url", url + "?" + connectionProperties); } else { d.setProperty("url", url); } d.setId(ds.getId()); d.setType(ds.getType()); d.setProperty("driver", properties.getDriver()); d.setProperty("user", properties.getUser()); d.setProperty("password", properties.getPassword()); d.setProperty("login-timeout", Integer.valueOf(this.toTime(ds.getConnectionTimeout()))); d.setProperty("max-idle-time", Integer.valueOf(this.toTime(ds.getIdleTimeout()))); d.setProperty("min-pool-size", ds.getMinimumPoolSize()); d.setProperty("max-pool-size", ds.getMaximumPoolSize()); d.setProperty("checkout-timeout", ds.getCheckoutTimeoutInMillis()); return d; } }
數據源描述信息包含哪些內容呢,我們結合上面源碼和下面的 datasources.xml配置來看,
每個data-source都有一個id; type默認jdbc; driver 默認為 com.mysql.jdbc.Driver、url、用戶名、密碼,登陸超時、連接池大小、超時檢測等等。

<data-source id="cat"> <maximum-pool-size>3</maximum-pool-size> <connection-timeout>1s</connection-timeout> <idle-timeout>10m</idle-timeout> <statement-cache-size>1000</statement-cache-size> <properties> <driver>com.mysql.jdbc.Driver</driver> <url><![CDATA[jdbc:mysql://192.168.20.67:3306/cat]]></url> <user>root</user> <password>f63hiccVEv0mMXi</password> <connectionProperties><![CDATA[useUnicode=true&autoReconnect=true]]></connectionProperties> </properties> </data-source>
---------------------
作者:曹號
來源:CSDN
原文:https://blog.csdn.net/caohao0591/article/details/80293833
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!