JetCache埋点的骚操作,不服不行啊
阐述背景
缓存是应对高并发绝对的利器,在很多业务场景允许的情况下,都可以使用缓存来提供性能。
既然用了缓存,那对缓存进行监控必不可少。比如缓存加载耗时,新增耗时等。
在 JetCache 中进行埋点操作,对于 Redis 的缓存没有问题,埋点之后的 Key 是完整的,完整的也就是 Cache 的 name+key,如下图:

除了对 Redis 的缓存做埋点,还对本地 缓存 Caffeine 也做了埋点操作,然后发现 Caffeine 的埋点有问题,问题在于 Cache 的 name 丢失了,如下图:

然后去官方的钉钉群了问了下维护人员,让我升级版本。然后我升级到最新的 2.6.0 还是不行,这不是坑我么 !
找出原因
正所谓自己动手,丰衣足食。直接看代码吧,首先看 Redis 为何 Cache name 没有丢失,原因是 Redis 的 Config 中有 keyPrefix,如下图:

然后在对 Redis 进行操作的时候,会构建缓存的 Key,构建 Key 的时候会带上 keyPrefix,所以 Redis 的 Key 是正常的。
com.alicp.jetcache.external.AbstractExternalCache
public byte[] buildKey(K key) {
try {
Object newKey = key;
if (key instanceof byte[]) {
newKey = key;
} else if (key instanceof String) {
newKey = key;
} else if (this.config.getKeyConvertor() != null) {
newKey = this.config.getKeyConvertor().apply(key);
}
return ExternalKeyUtil.buildKeyAfterConvert(newKey, this.config.getKeyPrefix());
} catch (IOException var3) {
throw new CacheException(var3);
}
}
然后来看 Caffeine 的 config 中是没有 Keyprefix 的,如下图:

然后在构建缓存 Key 的时候,也就是没有 Keyprefix,所以问题就出在这里。
com.alicp.jetcache.embedded.AbstractEmbeddedCache
public Object buildKey(K key) {
if (key == null) {
return null;
} else {
Object newKey = key;
Function<K, Object> keyConvertor = this.config.getKeyConvertor();
if (keyConvertor != null) {
newKey = keyConvertor.apply(key);
}
return newKey;
}
}
RedisCacheConfig 继承了 ExternalCacheConfig,ExternalCacheConfig 继承了 CacheConfig。
keyPrefix 定义在 ExternalCacheConfig 中。

而 EmbeddedCacheConfig 只继承了 CacheConfig,所以它自然就没有 keyPrefix 字段。

解决方案
原因找出来了,想要解决肯定是可以的。问题是这是个开源的框架,不是自己公司内部的代码。不过也可以直接将源码克隆下来,进行改造,然后打包发布到自己的私服中去就可以了。
将 EmbeddedCacheConfig 也继承 ExternalCacheConfig 就可以将 keyPrefix 透传下去,然后在 buildKey 的地方进行拼接。
还有一种比较投机取巧的方案,可以不用改变配置类的关系,在 config 中有 monitors 这个信息,里面存放的是缓存的监控信息,主要是记录缓存对应的操作类型,GET, PUT 这种,然后就是每个操作的执行时间,操作次数等一些统计的信息,最终会有一个线程定时将这些信息输出到日志中。
所以我们可以通过获取 monitors 中的 cacheName 来临时解决这个问题。

private String getCacheName() {
List<CacheMonitor> monitors = config.getMonitors();
if (CollectionUtils.isEmpty(monitors)) {
return "";
}
DefaultCacheMonitor cacheMonitor = (DefaultCacheMonitor) monitors.get(0);
String cacheName = cacheMonitor.getCacheName();
return cacheName;
}
功能代码: https://github.com/yinjihuan/kitty
关于作者 :尹吉欢,简单的技术爱好者,《Spring Cloud 微服务-全栈技术与案例解析》, 《Spring Cloud 微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。个人微信 jihuan900 ,欢迎勾搭。
我整理了一份很全的学习资料,感兴趣的可以微信搜索 「猿天地 」,回复关键字 「学习资料 」获取我整理好了的Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC分库分表,任务调度框架XXL-JOB,MongoDB,爬虫等相关资料。
JetCache埋点的骚操作,不服不行啊的更多相关文章
- Typescript骚操作,在TS里面直接插入HTML
Typescript骚操作,在TS里面直接插入HTML,还有语法提示 先给大家看一个图 因为我不喜欢用很重的框架,主要是并非专业UI,但是偶尔会用到,还是觉得直接element组装受不了,想想能在ts ...
- 闪电侠 Netty 小册里的骚操作
前言 即使这是一本小册,但基于"不提笔不读书"的理念,仍然有必要总结一下.此小册对于那些"硬杠 Netty 源码 却不曾在千万级生产环境上使用实操"的用户非常有 ...
- awk骚操作
一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...
- 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)
0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...
- UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)
题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...
- 关于map 及 map 骚操作
关于map这个东西 很冷门.................. 但是,这个博客带你稍微了解一下map: map用法:一般当作一个下表无穷大的数组 关于它的骚操作:map的鬼畜用法,可以 ...
- 通过HTTP的HEADER完成各种骚操作
作为一名专业的切图工程师,我从来不care网页的header,最多关心Status Code是不是200.但是HEADER真的很重要啊,客户端从服务器端获取内容,首先就是通过HEADER进行各种沟通! ...
- 洛谷 P1045 麦森数 (快速幂+高精度+算位数骚操作)
这道题太精彩了! 我一开始想直接一波暴力算,然后叫上去只有50分,50分超时 然后我改成万位制提高运算效率,还是只有50分 然后我丧心病狂开long long用10的10次方作为一位,也就是100亿进 ...
- Mac OS 上的一些骚操作
本帖记录个人在使用 Mac 操作系统上的一些骚操作,不断更新,以飨读者. 快速移动网页到顶部或底部 用双指上下划触摸板吗?NO,我们有更骚的操作: command + ↑ 回到顶部 command + ...
随机推荐
- java8之Stream流处理
简介 Stream 流处理,首先要澄清的是 java8 中的 Stream 与 I/O 流 InputStream 和 OutputStream 是完全不同的概念. Stream 机制是针对集合迭代器 ...
- ajax工作原理/实例
ajax是什么? 是一种创建交互式网页应用的一种网页技术.简单来说,就是向服务器发起请求,获得数据使交互性和用户体验更好. ajax不是一种新的技术,是一些技术的集合体.有 1.XHTML和CSS 2 ...
- Python package project
使用 Python 书写项目打包程序(已经存在 shell 的脚本,经过对比 Python 脚本的执行过程更加的可控人性化实现的功能相同) #!/usr/bin/env python # _*_cod ...
- Redis的事件机制
目录 一.Redis的运行过程 二.事件数据结构 2.1 文件事件数据结构 2.2 事件事件数据结构 3.3 事件循环 三.事件的注册过程 3.1 文件事件的注册过程 3.2 时间事件的注册过程 四. ...
- PHP fscanf() 函数
定义和用法 fscanf() 函数根据指定的格式对来自打开的文件的输入进行解析. 语法 fscanf(file,format,mixed) 参数 描述 file 必需.规定要检查的文件. format ...
- Android JNI之动态注册
所谓动态注册,就是不用像静态注册那样按规则严格的命名native方法,而是在加载so库的时候完成这个从Java方法到native方法的匹配工作,而这个匹配工作,需要我们写native代码来完成.下面直 ...
- windows:shellcode 代码远程APC注入和加载
https://www.cnblogs.com/theseventhson/p/13197776.html 上一章介绍了通用的shellcode加载器,这个加载器自己调用virtualAlloc分配 ...
- 如何优雅的设计 Spring Boot API 接口版本号
原文:https://blog.mariojd.cn/how-to-design-spring-boot-api-version-number-elegantly.html 一般来说,系统上线以后,需 ...
- 解决 IntelliJ IDEA占用C盘过大空间问题
原文地址:https://blog.csdn.net/weixin_44449518/article/details/103334235 问题描述: 在保证其他软件缓存不影响C盘可用空间的基础上,当我 ...
- 2017面向对象程序设计(Java)第十三周助教工作总结
时间飞逝,本学期即将接近尾声.不知不觉同学们已经学习java十三个星期了,想必同学们对Java课程体系及内容有了更加深入的理解,也应该摸索出了一套适用于自己的学习方法. 下面我对上周工作做以简单总结: ...