HickWall 详解

优质博文:IT-BLOG-CN

一、监控分类

【1】Tracing调用链:

【2】Logging日志:

【3】Metrics指标:在应用发布之后,会长时间存在的度量维度。某个接口的请求量、响应时间。

Metrics数据模型

二、Metirc 接入

【1】pom.xml中添加metric-client依赖

html 复制代码
<dependency>
    <groupId>com.ctrip.flight.intl.common</groupId>
    <artifactId>metric-client</artifactId>
    <version>4.0.5</version>
</dependency>

【2】执行命令mvn -DskipTests=true compile

【3】编辑MetricClientExampleApplication.java

java 复制代码
@SpringBootApplication
 public class MetricClientExampleApplication {
    SpringApplication.run(MetricClientExampleApplication.class, args);
}

@Bean
public CommandLineRunner commandLineRunner() {
    return args -> {
        TimeUnit time = TimeUnit.SECONDS;
        while (true) {
            Metric metric = Metric.create("hickwall_metric_client_example", "100016249", "SYS");
           ThreadLocalRandom random = ThreadLocalRandom.current();
           metric.withTag("caller", "Dante")
                 .withTag("bu", "SYS")
                 .recordOne("run_query", random.nextLong(100, 60000));
           metric.recordSize("run_times", random.nextLong(0, 100));
           metric.addGauge("run_changes", () -> random.nextLong(0, 100));
           time.sleep(120);
       }
    };
}

【4】Tomcat应用

yml 复制代码
hickwall.prefix=数据库名.+自定义名字(用于区分不同开发组组、不同项目)

推荐做法:数据库名.小组名.项目名

eg: hickwall.prefix=FLT.backendservice.offline.screenpopup

三、埋点

【1】普通记录: 下面用一个例子来演示recordOnerecordSize的用法。假如有一个航班查询接口,它根据传入的参数,返回匹配的所有航班。接口定义如下:

java 复制代码
public List<Flight> searchFlights(String dep, String arr, String date);

现在,我们关心这个接口的表现,具体为如下指标:

■ 这个接口每秒调用了多少次。

■ 这个接口每次调用花了多少时间。

■ 这个接口每次调用返回了多少条结果。

做法如下:

java 复制代码
public List<Flight> searchFlights(String dep, String arr, String date){
    // 记录请求开始的时间
    long startTime = System.currentTimeMillis();
     
    // 实际的搜索航班
    List<Flight> flights = doSearchFlights(dep, arr, date);
     
    // 当前时间减去开始时间,计算得到搜索航班实际执行的时间
    long timeUsed = System.currentTimeMillis() - startTime;
     
    // 埋点记录这个方法被调用了一次,以及这次调用使用的时间
    Metrics.recordOne("flight.search", timeUsed);
    // 埋点记录这次调用返回的航班的条数。
    Metrics.recordSize("flight.search", flights.size());
     
    return flights;
}

recordOnerecordSize的区别:

recordOne记录的值是qps。场景:引擎每秒成功多少次。

recordSize记录的值是平均值。场景:引擎每次返回的结果数量。

【2】下面演示addGauge的用法:假如系统内部有一个缓存,缓存的key的数量随着时间而改变。我们关心缓存的表现,指标如下:缓存的key随着时间是如何变化的。针对这种需求,recordOnerecordSize可能就不够用了,这时需要用addGauge。如下:

java 复制代码
@Service
public class Test {
 
    Map cache = new HashMap();
 
    @PostConstruct
    public void init() {
        Metrics.addGauge("cache", () -> cache.size());
    }
}

addGauge方法要求传入一个Supplier,这个Supplier应该返回一个整数值。Metrics会每分钟调用一次Supplier,并把它返回的整数值发送给hickwall

如果在3.2中自己new了一个Metric,上面例子中的Metrics要替换成new出来的metric对象。

四、使用 Tag

相同的指标名,可以记录不同的tag。在hickwall展示的时候,可以根据tag来分别展示指标。

提示:自定义的Tag名称 如果DB无法查询得到,目前是需要找Hickwall Support手动添加。
tag的使用如下:

java 复制代码
Metrics.withTag("clientAppId", "100000").recordOne("metricName");

五、超高频调用

如果调用的频率非常高(1000+qps),recordOnerecordSize的性能可能会不够用。这种情况下,需要使用forRecordOneforRecordSize来提高性能。

沿用4.1中的例子,代码要修改如下(注意第1/2行和第15/17行):

java 复制代码
private MetricOne COUNT_METRIC = Metrics.forRecordOne("flight.search");
private MetricSize SIZE_METRIC = Metrics.forRecordSize("flight.search");
 
public List<Flight> searchFlights(String dep, String arr, String date){
    // 记录请求开始的时间
    long startTime = System.currentTimeMillis();
 
    // 实际的搜索航班
    List<Flight> flights = doSearchFlights(dep, arr, date);
 
    // 当前时间减去开始时间,计算得到搜索航班实际执行的时间
    long timeUsed = System.currentTimeMillis() - startTime;
 
    // 埋点记录这个方法被调用了一次,以及这次调用使用的时间
    COUNT_METRIC.recordOne(timeUsed);
    // 埋点记录这次调用返回的航班的条数。
    SIZE_METRIC.recordSize(flights.size());
 
    return flights;
}

六、指标命名方式

前面第四节中,埋点使用的指标名并不是最终在hickwall中存储的指标名。

hickwall中存储的指标名规则如下:metricName=appPrefix.metricName.{count,time,size,value}

例如,假设appPrefixintlengine.common

记录方式 最终名称
recordOne("query") intlengine.common.query.count
recordOne("query", time) intlengine.common.query.count
intlengine.common.query.time
recordSize("queryResult") intlengine.common.queryResult.size
addGauge("resource", ()-> resources.size()) intlengine.common.resources.value

七、检查写入情况

打开指标查询,选择数据源和搜索指标名称,我看主要看两部分"查询"和"生成看板到Grafana"。下图为查询相关信息

数据源名的层次结构

生成看板到Grafana:

【1】数据源和指标查询语句必填

【2】dashboard选择必填:

■ 添加到已有的dashboard: 将当前的指标添加到已经存在的hickwall grafana dashboard中。

■ 新建dashbaord: 新建一个dashboard,并将当前的指标添加到新建的这个dashbord中。需要指定新的dashboard名称,并且重名的dashboard会新建失败。

【3】panel配置必填

■ 新建panel: 需要指定新的panel的名称

■ 已有的panel: 为已有的panel添加当前的指标语句

【4】别名legendFormat: 即这条线的名称,支持这种tag匹配格式非必填

【5】预览: 可以查看当前指标生成的线以及paneljson 配置。

效果图

八、尝试一下 PromQL

Grafana上创建一个看板,然后点击Add Query,在这个看起来有点唬人的页面里把Queries to改成APM-SYS,然后在那个大大的输入框里写下生命、宇宙与一切的答案:

不管多复杂的promQL表达式,返回值只有三种

1.瞬时向量,同一时间点的数据点

2.范围向量,同一个指标的一段时间范围内的数据点

3.数值,字面量,没有标签、时间戳

PromQL的运算逻辑是这样的:浏览器会按照选取的时间范围和显示器的大小选取合适的间隔,例如显示的曲线是3min一个数据点。后端会根据这个时间间隔分别计算每个时间段上的值,并赋予该时间段的起始时间戳。最后所有的段连接起来就是一条曲线。

九、看板

当我们使用PromQL查出了需要的数据,就可以继续调整看板的其它配置。常用的有:

Legend:图例。如果我们只希望显示数据中的caller这个tag的值,就可以在Legend中填写 ''

Min step:步长。如果希望图中每小时只显示一个点,就在这里填写1h

Visualization:点击左侧第二个图标进入,这里可以修改的配置项很多,比如:

Visualization:可以从默认的 Graph 改成多种其它图表,每种图表的使用方式各异,请自行探索 / 查阅文档

Axes -> Left Y -> Unit:改变默认的数值单位

Legend -> Values -> Total / Avg / Min / Max ...

General:左侧第三个图标,在这里可以给Panel取一个温暖的名字

Alert:左侧第四个图标,进入我们接下来要做的:配置告警

配置告警之前,记得点击右上角的Save Dashboard保存一下。

十、告警

点击Create Alert来创建一个新的告警规则。安心,在我们保存整个Dashboard之前,它都不会生效。

如果你看到很多大红的警示文字,不用担心,这只是审美问题。

首先,选择BU、产品线、AppID

然后给告警命名,Evaluate every 表示每隔多久执行一次这条告警规则,For 则表示在持续多久满足(我们马上就会填的)告警条件之后才真正发出告警。

接下来随便填一个阈值:

当使用avg()这个函数去算A这个查询语句取5m(也就是 5 分钟)内的数据的均值,要是它的结果IS ABOVE(大于) 1,就满足告警条件了,告警级别P3,而且不管现在几点都生效(Alert Time = All)。

对于一个已经保存过的Dashboard,填好以后我们就可以点右上角的Test Rule来试试它能不能正常运行。

最后,万一告警触发了,该通知谁呢?

这里看到,我们可以选: 各种方式的任意组合

AppID的管理员

■ 用户

■ 邮件组

Oncall

如果这样仍不能满足需求,还可以配置 自定义告警通知,来根据不同的告警级别进行配置,并选择Send to(通知方式):

■ 邮件

■ 短信

TTS语音

TripPal

相关推荐
utmhikari34 分钟前
【架构艺术】Go语言微服务monorepo的代码架构设计
后端·微服务·架构·golang·monorepo
蜡笔小新星37 分钟前
Flask项目框架
开发语言·前端·经验分享·后端·python·学习·flask
计算机学姐41 分钟前
基于Asp.net的驾校管理系统
vue.js·后端·mysql·sqlserver·c#·asp.net·.netcore
欢乐少年19043 小时前
SpringBoot集成Sentry日志收集-3 (Spring Boot集成)
spring boot·后端·sentry
夏天的味道٥4 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
堕落年代7 小时前
Maven匹配机制和仓库库设置
java·maven
功德+n7 小时前
Maven 使用指南:基础 + 进阶 + 高级用法
java·开发语言·maven