對任意突發性的無法預先感知的熱點數據,包括并不限于熱點數據(如突發大量請求同一個商品)、熱用戶(如惡意爬蟲刷子)、熱接口(突發海量請求同一個接口)等,進行毫秒級精準探測到。然后對這些熱數據、熱用戶等,推送到所有服務端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內存中