使用HotKey框架实现热数据的毫秒级探测与处理
# 简介
对任意突发性的无法预先感知的热点数据,包括并不限于热点数据(如突发大量请求同一个商品)、热用户(如恶意爬虫刷子)、热接口(突发海量请求同一个接口)等,进行毫秒级精准探测到。然后对这些热数据、热用户等,推送到所有服务端JVM内存中。
# hotkey框架的主要组成部分
![微信图片_20230819101942.png](https://cos.easydoc.net/44929674/files/llhe6sm7.png)
- ## etcd
etcd作为⼀个⾼性能的配置中⼼,可以以极⼩的资源占⽤,提供⾼效的监听订阅服务。主要⽤于存放规则配置,各worker的ip地址,以及探测出的热key、⼿⼯添加的热key等
- ## worker
worker端是⼀个独⽴部署的Java程序,启动后会连接etcd,并定期上报⾃⼰的ip信息,供client端获取地址并进⾏⻓连接。之后,主要就是对各个client发来的待测key进⾏累加计算,当达到etcd⾥设定的rule阈值后,将热key推送各个client。
## dashboard
控制台是⼀个带可视化界⾯的Java程序,也是连接到etcd,之后在控制台设置各个APP的key规则,譬如2秒出现20次算热key。然后当worker探测出来热key后,会将key发往etcd,dashboard也会监听热key信息,进⾏⼊库保存记录。同时,dashboard也可以⼿⼯添加、删除热key,供各个client端监听。
- ## client
在服务中添加的引⽤jar,引⼊后,就可以以便捷的⽅式去判断某key是否热key。同时,该jar完成了key上报、监听etcd⾥的rule变化、worker信息变化、热key变化,对热key进⾏本地caffeine缓存等.
# 安装
源码地址:
```
https://gitee.com/jd-platform-opensource/hotkey
```
测试可以直接下载源码下载直接跑,新建dashboard的数据库,更改数据库连接就可以直接启动了
## etcd安装
- 下载 (使用3.4.x以上对应自己系统的版本)
```
https://github.com/coreos/etcd/releases
// 参考
https://www.cnblogs.com/pyrene/p/8652879.html
```
- 解压 进入解压目录执行 etcd.exe 出现端口号不报错说明启动成功了。
![etct_start_secuccess_log.jpg](https://cos.easydoc.net/44929674/files/llhfpyqs.jpg)
## 启动worker
- worker 已经打好的jar包,下载地址
```
https://gitee.com/dssss/resource-library/tree/master/jd-hotkey/worker
```
- 启动服务
```
java -jar worker-0.0.4-SNAPSHOT.jar --etcd.server=127.0.01:2379
```
## 启动 dashboard
- dashboard jar包下载地址
```
https://gitee.com/dssss/resource-library/tree/master/jd-hotkey/dashboard
```
- 启动服务( 这个需要创建数据库并导入resource下db.sql文件。 配置一下application.yml里的数据库相关和etcdServer地址)
```
java -jar dashboard-0.0.2-SNAPSHOT.jar
```
- 访问 http://127.0.0.1:8081
账号:admin 密码:123456
![login.jpg](https://cos.easydoc.net/44929674/files/llhn7as0.jpg)
![index.jpg](https://cos.easydoc.net/44929674/files/llhnjc39.jpg)
# 在springboot中使用
- 配置app规则 在用户管理菜单中,添加一个新用户,设置他的APP名字,如hostkey。之后新添加的这个用户就可以登录dashboard给自己的APP设置规则了
```json
[
{
"desc":"* hotkey ",
"duration":60,
"interval":5,
"key":"*",
"prefix":false,
"threshold":3
}
]
```
![rule.jpg](https://cos.easydoc.net/44929674/files/llhpfq0l.jpg)
## 引入client jar包
```xml
<dependency>
<groupId>com.jd.platform.hotkey</groupId>
<artifactId>hotkey-client</artifactId>
<version>0.0.4-SNAPSHOT</version>
</dependency>
```
## 初始化
```java
@Component
public class HotKeyInit {
@Value("${etcd.server}")
private String etcdServer;
@Value("${spring.application.name}")
private String appName;
@PostConstruct
public void init() {
ClientStarter.Builder builder = new ClientStarter.Builder();
ClientStarter starter = builder.setAppName(appName).setEtcdServer(etcdServer).build();
starter.startPipeline();
}
}
```
## 测试
```java
@RestController
public class TestController {
@RequestMapping("/hotKey")
public Object hotKey(String key) {
if (!StringUtils.isEmpty(key) && JdHotKeyStore.isHotKey(key)) {
return "isHot";
} else {
return "noHot";
}
}
}
```
# api方法
1. boolean isHotKey(String key) ,该方法会返回该key是否是热key,如果是返回true,如果不是返回false,并且会将key上报到探测集群进行数量计算。该方法通常用于判断只需要判断key是否热、不需要缓存value的场景,如刷子用户、接口访问频率等。
2. Object get(String key),该方法返回该key本地缓存的value值,可用于判断是热key后,再去获取本地缓存的value值,通常用于redis热key缓存
3. void smartSet(String key, Object value),方法给热key赋值value,如果是热key,该方法才会赋值,非热key,什么也不做
4. Object getValue(String key),该方法是一个整合方法,相当于isHotKey和get两个方法的整合,该方法直接返回本地缓存的value。 如果是热key,则存在两种情况,1是返回value,2是返回null。返回null是因为尚未给它set真正的value,返回非null说明已经调用过set方法了,本地缓存value有值了。 如果不是热key,则返回null,并且将key上报到探测集群进行数量探测。
5. 其他查看 JdHotKeyStore 类