项目背景:
通常项目中,我们采用 grafana和prometheus 作为项目监控通常都是按照秒级别的采样监控,但是无法检测一个接口,一个热点用户毫秒级的监控。 hotkey 项目是一个针对热点探测,监控。将请求数据缓推送到服务端的 jvm 内存中,减少后端存储对持久化数据库的冲击,可以由使用者决定如何分配、使用这些热点 key , 可以用来做本地缓存,拒绝访问,热点熔断返回默认值等。这些数据在集群内能够保证一致性,实现业务隔离。 hotkey 是京东APP后台热数据探测框架,历经多次高压压测和2020年京东618、双11大促考验。每秒单机吞吐量(写入+对外推送)目前在70万左右稳定。
gitee 项目地址:
系统架构:
hotkey 采用的分布式集群架构,默认以 etcd 为服务注册中心,然后 hotkey-client 通过 etcd 获取 worker 的信息, 将监听到的热key 信息上报到 worker 上。在 hotkey-client 和 worker 之间采用长链接的方式(基于 netty)然后按照 key 的 hash 算法,分发到不同的 worker 进行计算。最后 worker 将计算出来的热 key 在进行推送到 hotkey-client 进行内存缓存。
安装步骤:
安装 etcd 作为注册中心
docker 安装命令
docker run -d \
-p 12379:2379 \
-p 12380:2380 \
-v /Users/zhengshaohong/etcd/data:/etcd-data/member \
--name exam-etcd \
quay.io/coreos/etcd:latest \
/usr/local/bin/etcd \
--name s1 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://0.0.0.0:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://0.0.0.0:2380 \
--initial-cluster s1=http://0.0.0.0:2380 \
--initial-cluster-token tkn \
--initial-cluster-state new
测试:
# 创建数据
docker exec exam-etcd etcdctl --endpoints=http://127.0.0.1:2379 set test_key hello_world
# 查询数据
docker exec exam-etcd etcdctl --endpoints=http://127.0.0.1:2379 get test_key
安装 hotkey dashboard
- 下载代码: gitee.com/jd-platform…
- 初始化数据库,脚本位置 dashboard/src/main/resources/db.sql 初始化脚本过后,我们需要检查密码是否正确 如果不匹配修改 3)然后启动: dashboard 4)访问 dashboard, ip:8081 默认登陆账户 admin , 密码:123456 登陆页面如下:
启动 worker
启动命令
java -jar $JAVA_OPTS worker-0.0.4-SNAPSHOT.jar --etcd.server=http://127.0.0.1:2379
app 配置规则 登陆 dashboard 后可以看到这个页面 创建用户,需要注意这个地方的用户名就是服务名, 可以选择新增按钮新增。
配置规则
规则配置代码示例:
[{"desc":"* hotkey ","duration":60,"interval":5,"key":"*","prefix":false,"threshold":3}]
配置 JSON 说明:
- key-(*代表任意以key为前缀),
- prefix-是否前缀,
- interval-间隔时间(秒),
- threshold-阈值,
- duration-缓存时间(秒),默认60
客户端集成 hotkey-client 引入 hotkey-client 依赖
<dependency>
<groupId>com.jd.platform.hotkey</groupId>
<artifactId>hotkey-client</artifactId>
<version>${version}</version>
</dependency>
初始化 hotkey client
@Component
public class HotKeyConfig {
@Value("${etcd.server}")
private String etcd;
@Value("${spring.application.name}")
private String appName;
@PostConstruct
public void init() {
ClientStarter.Builder builder = new ClientStarter.Builder();
ClientStarter starter = builder.setAppName(appName).setEtcdServer(etcd).build();
starter.startPipeline();
}
}
使用 hotkey api
@RestController
@RequestMapping
public class TestController {
@Resource
private Cache cache;
private Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("/hotKey")
public Object hotKey(String key) {
if (!StringUtils.isEmpty(key) && JdHotKeyStore.isHotKey(key)) {
return "isHot";
} else {
return "noHot";
}
}
}
测试
访问 /hotkey 接口,触发阈值过后就会显示 dashboad 查看实时热点如下 通过查询这个控制台,我们就很容易知道系统的热点位置,方便我们下一步的性能优化。