1. 程式人生 > >google的RateLimiter限流器的使用

google的RateLimiter限流器的使用

背景:A系統需要呼叫B,C,D系統,B,C,D系統沒有能力做限流,因此需要A系統針對B,C,D系統做限流,每秒傳送物件要求的請求數。可以使用下面的元件進行控制

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.RateLimiter;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * 公共限流器<p>
 *
 * 內部維持一個限流器集合<p>
 *
 * 同一個identify(身份),同一個限流上限值 公用一個限流器.<p>
 *
 * 如果某一個identify的限流值改了,則使用新的限流器.原有的限流器會因為快取失效而被回收。<p>
 */
public class CommonRateLimiterManager {


    /**
     * 限流器快取
     *
     * key:identify+permitsPerSnd
     *
     * value:限流器例項
     * */
    private static final Cache<String, RateLimiter> RATE_LIMITER_CACHE = CacheBuilder.newBuilder()
        .maximumSize(2000).expireAfterWrite(7, TimeUnit.DAYS).build();

    /**
     * 申請獲取一個許可<p>
     *
     * 同一個 identify 共享一個限速器<p>
     *
     * @param identify 身份資訊
     * @param permitsPerSnd 當前的限速值
     */
    public static void acquireOnePermit(final String identify, final double permitsPerSnd) {
        try {
            RateLimiter rateLimiter = RATE_LIMITER_CACHE.get(identify, new Callable<RateLimiter>() {

                /**
                 * Computes a result, or throws an exception if unable to do so.
                 *
                 * @return computed result
                 * @throws Exception if unable to compute a result
                 */
                @Override
                public RateLimiter call() throws Exception {
                    System.out.println("已建立限流元件-[identify={0}, permitsPerSnd={1}]."+identify+"--"+
                        permitsPerSnd);
                    return RateLimiter.create(permitsPerSnd);
                }
            });

            rateLimiter.acquire();
        } catch (Exception e) {
            System.out.println("獲取限流元件時異常,identify={0},permitsPerSnd={1}."+ identify+"--"+permitsPerSnd);
        }
    }

    /**
     * 如果獲取到就返回true.否則返回false.
     * 這個是不阻塞當前執行緒的
     * @param identify
     * @param permitsPerSnd
     */
    public static boolean tryAcquireOnePermit(final String identify, final double permitsPerSnd) {
        try {
            RateLimiter rateLimiter = RATE_LIMITER_CACHE.get(identify, new Callable<RateLimiter>() {

                /**
                 * Computes a result, or throws an exception if unable to do so.
                 *
                 * @return computed result
                 * @throws Exception if unable to compute a result
                 */
                @Override
                public RateLimiter call() throws Exception {
                    System.out.println("已建立限流元件-[identify={0}, permitsPerSnd={1}]."+identify+"--"+
                            permitsPerSnd);
                    return RateLimiter.create(permitsPerSnd);
                }
            });

            return rateLimiter.tryAcquire();
        } catch (Exception e) {
            System.out.println("獲取限流元件時異常,identify={0},permitsPerSnd={1}."+ identify+"--"+
                    permitsPerSnd);
            return false;
        }
    }
}