jd-hotkey探测热点key
对任意突发性的无法预先感知的热点数据,包括并不限于热点数据(如突发大量请求同一个商品)、热用户(如恶意爬虫刷子)、热接口(突发海量请求同一个接口)等,进行毫秒级精准探测到。然后对这些热数据、热用户等,推送到所有服务端JVM内存中,以大幅减轻对后端数据存储层的冲击,并可以由使用者决定如何分配、使用这些热key(譬如对热商品做本地缓存、对热用户进行拒绝访问、对热接口进行熔断或返回默认值)。这些热数据在整个服务端集群内保持一致性,并且业务隔离,worker端性能强悍。
适用场景:
1 mysql热数据本地缓存
2 redis热数据本地缓存
3 黑名单用户本地缓存
4 爬虫用户限流
5 接口、用户维度限流
6 单机接口、用户维度限流
7 集群用户维度限流
8 集群接口维度限流
环境部署
1 下载hotkey源码
hotkey: 京东App后台中间件,毫秒级探测热点数据,毫秒级推送至服务器集群内存,大幅降低热key对数据层查询压力
选择master分支下载
2 下载etcd
相当于注册中心作用
根据其文档,需要先启动etcd服务,下载地址:Releases · etcd-io/etcd
双击启动
3 启动worker
项目打包
启动服务
java -jar worker-0.0.4-SNAPSHOT.jar --etcd.server=http://127.0.0.1:2379 --etcd.workerPath=myapp
本例指定了etcd地址和workPath(控制台添加规则时,app名称要和该值保持一致)
4 启动dashboard
新建数据库 hotkey_db,并导入表,表来自db.sql
启动dashboard
java -jar dashboard-0.0.2-SNAPSHOT.jar --etcd.server=http://127.0.0.1:2379
访问http://127.0.0.1:8081(端口号可以通过dashboard的yml配置文件指定)
项目中接入hotkey
新建springboot项目
导入jar
文档中只是提到了导入client的jar,但是没有提到具体的jar的配置
开始导入了如下的jar,但是实际测试时,无法检测hotkey
<!-- 该jar无法使hotkey生效 --><dependency><groupId>io.github.ck-jesse</groupId><artifactId>jd-hotkey-client</artifactId><version>2.0.0</version></dependency>
只能对源码的client进行打包并导入
在springboot项目中新建lib目录,拷贝hotkey-client-0.0.4-SNAPSHOT-jar-with-dependencies.jar到lib目录
通过maven导入该jar
<dependency><groupId>com.jd.platform.hotkey</groupId><artifactId>hotkey-client</artifactId><version>0.0.4-SNAPSHOT</version><scope>system</scope><systemPath>${project.basedir}/lib/hotkey-client-0.0.4-SNAPSHOT-jar-with-dependencies.jar</systemPath></dependency>
yml配置
#etcd的地址,如有多个用逗号分隔
etcd:server: ${etcdServer:https://127.0.0.1:2379}
# server: ${etcdServer:http://10.170.161.91:2379}
# server: http://open-etcd.jd.com:2000
spring:application:name: ${name:myapp}###############################---redis---##############################
# redis:
# host: ${REDIS_HOST:127.0.0.1}
# port: ${REDIS_PORT:6379}
# password: ${REDIS_PASSWORD:}
server:port: 9999
读取yml并初始化对象
package com.qfedu.hotkeytest;import com.jd.platform.hotkey.client.ClientStarter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;@Component
public class Starter {@Value("${etcd.server}")private String etcd;@Value("${spring.application.name}")private String appName;@PostConstructpublic void init() {ClientStarter.Builder builder = new ClientStarter.Builder();ClientStarter starter = builder.setAppName(appName).setEtcdServer(etcd).build();starter.startPipeline();}}
在dashboard中添加用户
添加用户时指定app名称,和启动worker时指定的workPath值保持一致
添加规则
本例表示,5秒内,访问aaa前缀的key超过10次,则认为是热点key,并缓存60秒
通过控制层测试
@RequestMapping("/hotKey")public Object hotKey(String key) {if (!StringUtils.isEmpty(key) && JdHotKeyStore.isHotKey(key)) {return "isHot";} else {return "noHot";}}
5秒内,访问该接口超过10次,自动生成缓存
jd-hotkey通过Caffeine将数据缓存到服务器的jvm内存中