sentinel 官方文档_Sentinel控制台监控数据持久化到MySQL数据库
閱讀文本大概需要3分鐘。
? ? ? ?根據(jù)官方wiki文檔,Sentinel控制臺(tái)的實(shí)時(shí)監(jiān)控?cái)?shù)據(jù),默認(rèn)僅存儲(chǔ) 5 分鐘以?xún)?nèi)的數(shù)據(jù)。如需持久化,需要定制實(shí)現(xiàn)相關(guān)接口。
https://github.com/alibaba/Sentinel/wiki/在生產(chǎn)環(huán)境中使用-Sentinel
給出了指導(dǎo)步驟:
自行擴(kuò)展實(shí)現(xiàn) MetricsRepository 接口;
注冊(cè)成 Spring Bean 并在相應(yīng)位置通過(guò) @Qualifier 注解指定對(duì)應(yīng)的 bean name 即可;
0x01:MetricsRepository接口定義
package?com.alibaba.csp.sentinel.dashboard.repository.metric;import?java.util.List;public?interface?MetricsRepository<T>?{void?save(T?metric);void?saveAll(Iterable?metrics);List?queryByAppAndResourceBetween(String?app,?String?resource,?long?startTime,?long?endTime);List?listResourcesOfApp(String?app);}
該接口就只定義4個(gè)方法,分別用于保存和查詢(xún)Sentinel的metric數(shù)據(jù)。注釋其實(shí)很清楚了,解析如下:
save:保存單個(gè)metric
saveAll:保存多個(gè)metric
queryByAppAndResourceBetween:通過(guò)應(yīng)用名稱(chēng)、資源名稱(chēng)、開(kāi)始時(shí)間、結(jié)束時(shí)間查詢(xún)metric列表
listResourcesOfApp:通過(guò)應(yīng)用名稱(chēng)查詢(xún)資源列表
目前該接口只有一個(gè)基于內(nèi)存級(jí)別的實(shí)現(xiàn)類(lèi):com.alibaba.csp.sentinel.dashboard.repository.metric.InMemoryMetricsRepository。
另外還有一個(gè)實(shí)體類(lèi)com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity,如下圖
梳理了相關(guān)的類(lèi)關(guān)系就可以實(shí)現(xiàn)了。
0x02:根據(jù)MetricEntity新建數(shù)據(jù)庫(kù)和新建實(shí)體類(lèi)
建表語(yǔ)句如下
--?創(chuàng)建監(jiān)控?cái)?shù)據(jù)表CREATE?TABLE?`t_sentinel_metric`?(`id`?INT?NOT?NULL?AUTO_INCREMENT?COMMENT?'id,主鍵',`gmt_create`?DATETIME?COMMENT?'創(chuàng)建時(shí)間',`gmt_modified`?DATETIME?COMMENT?'修改時(shí)間',`app`?VARCHAR(100)?COMMENT?'應(yīng)用名稱(chēng)',`timestamp`?DATETIME?COMMENT?'統(tǒng)計(jì)時(shí)間',`resource`?VARCHAR(500)?COMMENT?'資源名稱(chēng)',`pass_qps`?INT?COMMENT?'通過(guò)qps',`success_qps`?INT?COMMENT?'成功qps',`block_qps`?INT?COMMENT?'限流qps',`exception_qps`?INT?COMMENT?'發(fā)送異常的次數(shù)',`rt`?DOUBLE?COMMENT?'所有successQps的rt的和',`_count`?INT?COMMENT?'本次聚合的總條數(shù)',`resource_code`?INT?COMMENT?'資源的hashCode',INDEX?app_idx(`app`)?USING?BTREE,INDEX?resource_idx(`resource`)?USING?BTREE,INDEX?timestamp_idx(`timestamp`)?USING?BTREE,??PRIMARY?KEY?(`id`)
)?ENGINE=INNODB?DEFAULT?CHARSET=utf8;
實(shí)體類(lèi)如下
package?com.alibaba.csp.sentinel.dashboard.datasource.entity;import?javax.persistence.*;import?java.io.Serializable;import?java.util.Date;/**?*?@author?2230
?*
?*/@Entity@Table(name?=?"t_sentinel_metric")public?class?MetricDto?implements?Serializable?{private?static?final?long?serialVersionUID?=?7200023615444172715L;/**id,主鍵*/@Id@GeneratedValue@Column(name?=?"id")private?Long?id;/**創(chuàng)建時(shí)間*/@Column(name?=?"gmt_create")private?Date?gmtCreate;/**修改時(shí)間*/@Column(name?=?"gmt_modified")private?Date?gmtModified;/**應(yīng)用名稱(chēng)*/@Column(name?=?"app")private?String?app;/**統(tǒng)計(jì)時(shí)間*/@Column(name?=?"timestamp")private?Date?timestamp;/**資源名稱(chēng)*/@Column(name?=?"resource")private?String?resource;/**通過(guò)qps*/@Column(name?=?"pass_qps")private?Long?passQps;/**成功qps*/@Column(name?=?"success_qps")private?Long?successQps;/**限流qps*/@Column(name?=?"block_qps")private?Long?blockQps;/**發(fā)送異常的次數(shù)*/@Column(name?=?"exception_qps")private?Long?exceptionQps;/**所有successQps的rt的和*/@Column(name?=?"rt")private?Double?rt;/**本次聚合的總條數(shù)*/@Column(name?=?"_count")private?Integer?count;/**資源的hashCode*/@Column(name?=?"resource_code")private?Integer?resourceCode;//?get??set?方法省略
}
0x03:pom.xml添加依賴(lài)
因?yàn)槭腔贘PA和MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn),所以需要添加JPA依賴(lài)和MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)依賴(lài)
???<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-data-jpaartifactId><version>${spring.boot.version}version>dependency><dependency><groupId>mysqlgroupId><artifactId>mysql-connector-javaartifactId><version>5.1.47version>dependency>0x04:實(shí)現(xiàn)MetricsRepository?接口,把數(shù)據(jù)持久化到MySQL數(shù)據(jù)庫(kù)
注意實(shí)現(xiàn)添加@Repository("jpaMetricsRepository")配置
package?com.alibaba.csp.sentinel.dashboard.repository.metric;import?java.time.Instant;import?java.util.ArrayList;import?java.util.Date;import?java.util.HashMap;import?java.util.List;import?java.util.Map;import?java.util.stream.Collectors;import?javax.persistence.EntityManager;import?javax.persistence.PersistenceContext;import?javax.persistence.Query;import?org.springframework.beans.BeanUtils;import?org.springframework.stereotype.Repository;import?org.springframework.transaction.annotation.Transactional;import?org.springframework.util.CollectionUtils;import?com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricDto;import?com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;import?com.alibaba.csp.sentinel.util.StringUtil;/**?*?https://www.cnblogs.com/yinjihuan/p/10574998.html
?*?https://www.cnblogs.com/cdfive2018/p/9838577.html
?*?https://blog.csdn.net/wk52525/article/details/104587239/
?*?https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
?*?
?*?@author?2230
?*
?*/@Transactional@Repository("jpaMetricsRepository")
public?class?JpaMetricsRepository?implements?MetricsRepository<MetricEntity>?{@PersistenceContext
????private?EntityManager?em;@Override
????public?void?save(MetricEntity?metric)?{if?(metric?==?null?||?StringUtil.isBlank(metric.getApp()))?{return;
????????}
????????MetricDto?metricDto?=?new?MetricDto();
????????BeanUtils.copyProperties(metric,?metricDto);
????????em.persist(metricDto);
????}@Override
????public?void?saveAll(Iterable?metrics)?{if?(metrics?==?null)?{return;
????????}
????????metrics.forEach(this::save);
????}@Override
????public?List?queryByAppAndResourceBetween(String?app,?String?resource,?long?startTime,?long?endTime)?{List?results?=?new?ArrayList();if?(StringUtil.isBlank(app))?{return?results;
????????}if?(StringUtil.isBlank(resource))?{return?results;
????????}
????????StringBuilder?hql?=?new?StringBuilder();
????????hql.append("FROM?MetricDto");
????????hql.append("?WHERE?app=:app");
????????hql.append("?AND?resource=:resource");
????????hql.append("?AND?timestamp>=:startTime");
????????hql.append("?AND?timestamp<=:endTime");
????????Query?query?=?em.createQuery(hql.toString());
????????query.setParameter("app",?app);
????????query.setParameter("resource",?resource);
????????query.setParameter("startTime",?Date.from(Instant.ofEpochMilli(startTime)));
????????query.setParameter("endTime",?Date.from(Instant.ofEpochMilli(endTime)));List?metricDtos?=?query.getResultList();if?(CollectionUtils.isEmpty(metricDtos))?{return?results;
????????}for?(MetricDto?metricDto?:?metricDtos)?{
????????????MetricEntity?metricEntity?=?new?MetricEntity();
????????????BeanUtils.copyProperties(metricDto,?metricEntity);
????????????results.add(metricEntity);
????????}return?results;
????}@Override
????public?List<String>?listResourcesOfApp(String?app)?{List<String>?results?=?new?ArrayList<>();if?(StringUtil.isBlank(app))?{return?results;
????????}
????????StringBuilder?hql?=?new?StringBuilder();
????????hql.append("FROM?MetricDto");
????????hql.append("?WHERE?app=:app");
????????hql.append("?AND?timestamp>=:startTime");
????????long?startTime?=?System.currentTimeMillis()?-?1000?*?60;
????????Query?query?=?em.createQuery(hql.toString());
????????query.setParameter("app",?app);
????????query.setParameter("startTime",?Date.from(Instant.ofEpochMilli(startTime)));List?metricDtos?=?query.getResultList();if?(CollectionUtils.isEmpty(metricDtos))?{return?results;
????????}List?metricEntities?=?new?ArrayList();for?(MetricDto?metricDto?:?metricDtos)?{
????????????MetricEntity?metricEntity?=?new?MetricEntity();
????????????BeanUtils.copyProperties(metricDto,?metricEntity);
????????????metricEntities.add(metricEntity);
????????}Map<String,?MetricEntity>?resourceCount?=?new?HashMap<>(32);for?(MetricEntity?metricEntity?:?metricEntities)?{String?resource?=?metricEntity.getResource();if?(resourceCount.containsKey(resource))?{
????????????????MetricEntity?oldEntity?=?resourceCount.get(resource);
????????????????oldEntity.addPassQps(metricEntity.getPassQps());
????????????????oldEntity.addRtAndSuccessQps(metricEntity.getRt(),?metricEntity.getSuccessQps());
????????????????oldEntity.addBlockQps(metricEntity.getBlockQps());
????????????????oldEntity.addExceptionQps(metricEntity.getExceptionQps());
????????????????oldEntity.addCount(1);
????????????}?else?{
????????????????resourceCount.put(resource,?MetricEntity.copyOf(metricEntity));
????????????}
????????}//?Order?by?last?minute?b_qps?DESC.return?resourceCount.entrySet()
????????????????.stream()
????????????????.sorted((o1,?o2)?->?{
????????????????????MetricEntity?e1?=?o1.getValue();
????????????????????MetricEntity?e2?=?o2.getValue();int?t?=?e2.getBlockQps().compareTo(e1.getBlockQps());if?(t?!=?0)?{return?t;
????????????????????}return?e2.getPassQps().compareTo(e1.getPassQps());
????????????????})
????????????????.map(Map.Entry::getKey)
????????????????.collect(Collectors.toList());
????}
}
0x05:application.properties配置文件添加數(shù)據(jù)庫(kù)配置
#?datasourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://127.0.0.1:3306/gateway_v2?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
#?spring?data?jpa
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=false
主要配置數(shù)據(jù)庫(kù)連接信息和JPA的配置項(xiàng),JPA使用Hibernate實(shí)現(xiàn)。
0x06:數(shù)據(jù)庫(kù)持久化換成JpaMetricsRepository實(shí)現(xiàn)
找到如下兩個(gè)類(lèi)
com.alibaba.csp.sentinel.dashboard.controller.MetricControllercom.alibaba.csp.sentinel.dashboard.metric.MetricFetcher在metricStore屬性上添加多一個(gè)@Qualifier("jpaMetricsRepository")注解,如下圖
0x07:驗(yàn)證
設(shè)置sentinel-dashboard工程的啟動(dòng)參數(shù)
-Dserver.port=8080?-Dcsp.sentinel.dashboard.server=localhost:8080?-Dproject.name=sentinel-dashboard具體可以參考【?Sentinel如何進(jìn)行流量監(jiān)控 】;可以發(fā)現(xiàn)數(shù)據(jù)已經(jīng)保存到MySQL數(shù)據(jù)庫(kù)。
備注:以上代碼改造都是在sentinel-dashboard項(xiàng)目上。
參考:https://www.cnblogs.com/cdfive2018/p/9838577.html☆
往期精彩
☆
01?Sentinel如何進(jìn)行流量監(jiān)控
02?Nacos源碼編譯
03?基于Apache Curator框架的ZooKeeper使用詳解
04?spring boot項(xiàng)目整合x(chóng)xl-job
05?互聯(lián)網(wǎng)支付系統(tǒng)整體架構(gòu)詳解
關(guān)注我
每天進(jìn)步一點(diǎn)點(diǎn)
喜歡!在看?總結(jié)
以上是生活随笔為你收集整理的sentinel 官方文档_Sentinel控制台监控数据持久化到MySQL数据库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 放个手机在单位自动打卡_1秒识别打卡,无
- 下一篇: python2连接mysql_mysql