JD hotkey是一個非常好用的京東熱點數據分析軟件,對任意突發性的無法預先感知的熱點請求,都可以進行毫秒級精準探測到。 然后對這些熱數據、熱用戶等,推送到該應用部署的所有機器JVM內存中,以大幅減輕對后端數據存儲層的沖擊。熱數據探測并推送至集群各個服務器, 這些熱key在整個應用集群內保持一致性。
軟件介紹
JD-hotkey是京東APP后臺熱數據探測框架,歷經多次高壓壓測和2020年京東618大促考驗。在上線運行的這段時間內,每天探測的key數量數十億計,精準捕獲了大量爬蟲、刷子用戶,另準確探測大量熱門商品并毫秒級推送到各個服務端內存,大幅降低了熱數據對數據層的查詢壓力,提升了應用性能。
對任意突發性的無法預先感知的熱點請求,包括并不限于熱點數據(如突發大量請求同一個商品)、熱用戶(如爬蟲、刷子)、熱接口(突發海量請求同一個接口)等,進行毫秒級精準探測到。 然后對這些熱數據、熱用戶等,推送到該應用部署的所有機器JVM內存中,以大幅減輕對后端數據存儲層的沖擊,并可以由客戶端決定如何使用這些熱key(譬如對熱商品做本地緩存、對熱用戶進行拒絕訪問、對熱接口進行熔斷或返回默認值)。 這些熱key在整個應用集群內保持一致性。
核心功能:熱數據探測并推送至集群各個服務器
應用場景
JD-hotkey適用場景:
1、mysql熱數據本地緩存
2、redis熱數據本地緩存
3、黑名單用戶本地緩存
4、爬蟲用戶限流
5、接口、用戶維度限流
6、單機接口、用戶維度限流限流
7、集群用戶維度限流
8、集群接口維度限流
安裝方法
1、安裝etcd
在etcd下載頁面下載對應操作系統的etcd
2、啟動worker(集群) 下載并編譯好代碼,將worker打包為jar,啟動即可。如:
java -jar $JAVA_OPTS worker-0.0.1-SNAPSHOT.jar --etcd.server=${etcdServer}
worker可供配置項如下:
etcdServer為etcd集群的地址,用逗號分隔
JAVA_OPTS是配置的JVM相關,可根據實際情況配置
threadCount為處理key的線程數,不指定時由程序來計算。
workerPath代表該worker為哪個應用提供計算服務,譬如不同的應用appName需要用不同的worker進行隔離,以避免資源競爭。
3、啟動控制臺
下載并編譯好dashboard項目,創建數據庫并導入resource下db.sql文件。 配置一下application.yml里的數據庫相關和etcdServer地址。
啟動dashboard項目,訪問ip:8081,即可看到界面。
其中節點信息里,即是當前已啟動的worker列表。
規則配置就是為各app設置規則的地方,初次使用時需要先添加APP。在用戶管理菜單中,添加一個新用戶,設置他的APP名字,如sample。之后新添加的這個用戶就可以登錄dashboard給自己的APP設置規則了,登錄密碼默認123456。
如圖就是一組規則,譬如其中as__開頭的熱key的規則就是interval-2秒內出現了threshold-10次就認為它是熱key,它就會被推送到jvm內存中,并緩存60秒,prefix-true代表前綴匹配。那么在應用中,就可以把一組key,都用as__開頭,用來探測。
4、client端接入使用
引入client的pom依賴。
在應用啟動的地方初始化HotKey,譬如
@PostConstruct public void initHotkey() { ClientStarter.Builder builder = new ClientStarter.Builder(); ClientStarter starter = builder.setAppName("appName").setEtcdServer("http://1.8.8.4:2379,http://1.1.4.4:2379,http://1.1.1.1:2379").build(); starter.startPipeline(); }
其中還可以setCaffeineSize(int size)設置本地緩存最大數量,默認5萬,setPushPeriod(Long period)設置批量推送key的間隔時間,默認500ms,該值越小,上報熱key越頻繁,相應越及時,建議根據實際情況調整,如單機每秒qps10個,那么0.5秒上報一次即可,否則是空跑。該值最小為1,即1ms上報一次。
注意:
如果原有項目里使用了guava,需要升級guava為以下版本,否則過低的guava版本可能發生jar包沖突。或者刪除自己項目里的guava的maven依賴,guava升級不會影響原有任何邏輯。
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.2-jre</version> <scope>compile</scope> </dependency>
有時可能項目里沒有直接依賴guava,但是引入的某個pom里引了guava,也需要將guava排除掉。
常見問題
1、worker掛了怎么辦
client根據worker的數量對key進行hash后分發,同一個key一定會被發往同一個worker。譬如4臺,掛了一臺,key就自動hash到另外3臺。那么這個過程中,就會丟失最多一個探測周期內的所有發來的key,譬如2秒10次算熱,那么就可能全部被rehash,丟失這2秒的數據。
它的影響是什么呢?我要不要去存下來所有發來的key呢?很多人都會問的問題。
首先掛機,那是極其罕見的事件,即便掛了,對于特別熱的key,完全不影響,hash丟幾秒,不影響它繼續瞬間變熱。對于不熱的key,它掛不掛,它也熱不了。對于那些將熱未熱的,可能會這次讓它熱不起來,但沒有什么影響,業務服務完全可以吃下這個熱key。而加上一堆別的組件如存儲、worker間通信傳輸key等,它的復雜度,性能都會影響很大。
所以它掛了對系統沒有任何影響
2、為什么全部要worker匯總計算,而不是客戶端自己計算
首先,客戶端是會本地累加的,在固定的上報周期內,如500ms內,本地就是在累加,每500ms批量上報給worker一次。如果上報頻率很高,如10ms一次,那么大概率本地同一個key是沒有累加。
有人會說,把這個間隔拉長,譬如本地計算3秒后,本地判定熱key,再上報給其他機器。那么這種場景首先對于京東是不可行的,哪怕1秒都不行。譬如一個用戶刷子,它在非常頻繁地刷接口,一秒刷了500次,而正常用戶一秒最多點5次,它已經是非常嚴重的刷子了。但我們本地還是判斷不出來它是不是刷子。為什么?機器多。
隨便一個app小組都有數千臺機器,一秒500次請求,一個機器連1次都平均不到,大部分是0次,本地如何判斷它是刷子呢?總不能訪問我一次就算它刷吧。
然后搶購場景,有些秒殺商品,1-2秒就沒了,流量就停了,你本地計算了3秒,才去上報,那活動已經結束了,你的熱key再推送已經沒價值了。我們就要在活動即將開始之前的可能在10ms內,就要該商品被推送到所有client的jvm里去,根本等不了1秒。
3、為什么是worker推送,而不是worker發送熱key到etcd,客戶端直接監 聽etcd獲取熱key
(1) worker和client是長連接,產生熱key后,直接推送過去,鏈路短,耗時少。如果是發到etcd,客戶端再通過etcd獲取,多了一層中轉,耗時明顯增加。
(2) etcd性能不夠,存在單點風險。譬如我有5000臺client,每秒產生100個熱key,那么每秒就對應50萬次推送。我用2臺worker即可輕松完成,隨著worker的橫向擴展,每秒的推送上限線性增加。但無論是etcd、redis等等任何組件,都不可能做到1秒50萬次拉取或推送,會瞬間cpu爆滿卡死。因為worker是各自隔離的,而etcd是單點的。實際情況下,也不止5000臺client,每秒也不止100個熱key,只有當前的架構能支撐。
4、為什么是etcd,不是zookeeper之類的
etcd里面具備一個過期刪除的功能,你可以設置一個key幾秒過期,etcd會自動刪除它,刪除時還會給所有監 聽的client回調,這個功能在框架里是在用的,別的配置中心沒有這個功能。
etcd的性能和穩定性、低負載等各項指標非常優異,完全滿足我們的需求。而zk在很多暴漲流量前和高負載下,并不是那么穩定,性能也差的遠。
標簽: 源碼相關
-
7 簡單搜索天氣組件
裝機必備軟件
網友評論