使用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 类