億級流量網(wǎng)站架構(gòu)核心技術(shù):限流詳解之節(jié)流
上接聊聊高并發(fā)系統(tǒng)之限流特技-1、聊聊高并發(fā)系統(tǒng)之限流特技-2,本篇摘自《億級流量網(wǎng)站架構(gòu)核心技術(shù)》第四章 限流詳解,在之前兩篇文章的基礎(chǔ)上增加了節(jié)流部分。
有時(shí)候我們想在特定時(shí)間窗口內(nèi)對重復(fù)的相同事件最多只處理一次,或者想限制多個(gè)連續(xù)相同事件最小執(zhí)行時(shí)間間隔,那么可使用節(jié)流(Throttle)實(shí)現(xiàn),其防止多個(gè)相同事件連續(xù)重復(fù)執(zhí)行。節(jié)流主要有如下幾種用法:throttleFirst、throttleLast、throttleWithTimeout。
1. throttleFirst/throttleLast
throttleFirst/ throttleLast是指在一個(gè)時(shí)間窗口內(nèi),如果有重復(fù)的多個(gè)相同事件要處理,則只處理***個(gè)或***一個(gè)。其相當(dāng)于一個(gè)事件頻率控制器,把一段時(shí)間內(nèi)重復(fù)的多個(gè)相同事件變?yōu)橐粋€(gè),減少事件處理頻率,從而減少無用處理,提升性能。
如上圖所示,throttleFirst在一個(gè)時(shí)間窗口內(nèi)只會(huì)處理該時(shí)間窗口內(nèi)的***個(gè)事件。
而throttleLast會(huì)處理該時(shí)間窗口內(nèi)的***一個(gè)事件。
一個(gè)場景是網(wǎng)頁中的resize、scroll和mousemove 事件,當(dāng)我們改變?yōu)g覽器大小時(shí)會(huì)觸發(fā)resize事件,而滾動(dòng)頁面元素時(shí)會(huì)觸發(fā)scroll事件。當(dāng)我們快速連續(xù)執(zhí)行這些操作時(shí)會(huì)連續(xù)觸發(fā)這些事件,那么可能因造成UI反應(yīng)慢、瀏覽器卡頓,因此節(jié)流就派上用場了。對于前端開發(fā)可以使用jquery-throttle-debounce-plugin實(shí)現(xiàn),而Android開發(fā)可以使用RxAndroid實(shí)現(xiàn)。
2 throttleWithTimeout
throttleWithTimeout也叫做debounce(去抖),限制兩個(gè)連續(xù)事件的先后執(zhí)行時(shí)間不得小于某個(gè)時(shí)間窗口。
如上圖所示,throttleWithTimeout限制兩個(gè)連續(xù)事件的最小間隔時(shí)間窗口。throttleFirst/ throttleLast是基于決定時(shí)間做的處理,是以固定時(shí)間窗口為基準(zhǔn),對同一個(gè)固定時(shí)間窗口內(nèi)的多個(gè)連續(xù)事件最多只處理一個(gè)。而throttleWithTimeout是基于兩個(gè)連續(xù)事件的相對時(shí)間,當(dāng)兩個(gè)連續(xù)事件的間隔時(shí)間小于最小間隔時(shí)間窗口,就會(huì)丟棄上一個(gè)事件,而如果***一個(gè)事件等待了最小間隔時(shí)間窗口后還沒有新的事件到來,那么會(huì)處理***一個(gè)事件。
如搜索關(guān)鍵詞自動(dòng)補(bǔ)全,如果用戶每錄入一個(gè)字就發(fā)送一次請求,而先輸入的字的自動(dòng)補(bǔ)全會(huì)被很快到來的下一個(gè)字符覆蓋,那么會(huì)導(dǎo)致先期的自動(dòng)補(bǔ)全是無用的。throttleWithTimeout就是來解決這個(gè)問題的,通過它來減少頻繁的網(wǎng)絡(luò)請求,避免每輸入一個(gè)字就導(dǎo)致一次請求。
使用RxJava 1.2.0實(shí)現(xiàn)的測試代碼。
- Observable
 - .create(new Observable.OnSubscribe<Integer>(){
 - @Override
 - public void call(Subscriber<? super Integer> subscriber) {
 - //next實(shí)現(xiàn):Thread.sleep(millis); subscriber.onNext(i);
 - next(subscriber, 1,0); //0ms
 - next(subscriber, 2,50); //50ms
 - next(subscriber, 3,50); //100ms
 - next(subscriber, 4,30); //130ms
 - next(subscriber, 5, 40); //170ms
 - next(subscriber, 6,130); //300ms
 - subscriber.onCompleted();
 - }
 - })
 - .subscribeOn(Schedulers.newThread())
 - .throttleWithTimeout(100,TimeUnit.MILLISECONDS)
 - .subscribe(new Subscriber<Integer>() {
 - ……
 - @Override
 - public void onNext(Integer i) {
 - System.out.println("==" + i);
 - }
 - });
 
【本文是51CTO專欄作者張開濤的原創(chuàng)文章,作者微信公眾號:開濤的博客( kaitao-1234567)】

















 
 
 









 
 
 
 