【Java項目】自定義注解 + AOP + Guava Limiter(優(yōu)雅實現(xiàn)

【Java項目】自定義注解 + AOP + Guava Limiter(優(yōu)雅實現(xiàn)接口限流)
1、概述
在互聯(lián)網(wǎng)項目開發(fā)過程中,對于某些高頻或者在高并發(fā)環(huán)境下使用的接口,可能會在某一時候遇到突發(fā)很高的流量,瞬時被大量調(diào)用。為保證應(yīng)用服務(wù)穩(wěn)定運行,需要對高并發(fā)場景下接口進行限流處理,通過接口限流一定程度上也可以防止接口被惡意調(diào)用。這里主要介紹下采用自定義注解、切面編程、Guava的Limiter實現(xiàn)接口限流。
2、自定義注解
Java自定義注解是一種非常強大的語法結(jié)構(gòu),允許開發(fā)者自定義注解,自定義注解可以為程序添加元數(shù)據(jù)信息、代碼分析、運行時處理、框架集成提供非常大的便利。
2.1 使用場景介紹
- 標(biāo)記:可以用注解來標(biāo)記代碼,便于開發(fā)人員或者工具根據(jù)注解執(zhí)行某些操作或者特殊處理;
- 配置:用于配置類、方法、屬性的等參數(shù)和屬性值,使開發(fā)人員可以通過注解指定配置信息;
- 檢查:可以通過注解來檢查代碼正確性、合法性,便于及時發(fā)現(xiàn)代碼錯誤;
- 文檔:用于生成代碼文檔、API文檔等,例如Swagger相關(guān)注解。
2.2 語法結(jié)構(gòu)
?@Target(ElementType.METHOD) ?@Retention(RetentionPolicy.RUNTIME) ?public @interface Limiter { ???// 默認(rèn)每秒放入桶中的令牌數(shù) ???double limitNum() default 5; ???// 限流器名稱,使用該注解的每一個方法上,保證全局唯一性 ???String name() default ""; ?}
2.3 使用說明
- 自定義注解一般會與Spring AOP配合使用,通過定義將注解定義為切入點,獲取到使用了這個注解的方法或者類,然后根據(jù)注解信息做一些處理;
- 有時候也會與RequestBodyAdvice 、部分?jǐn)r截器一起使用,通過獲取對應(yīng)方法中包含該注解進行處理;
- 主要還是使用反射技術(shù),獲取到包含注解的類、方法或字段,然后進行對應(yīng)業(yè)務(wù)處理。
AOP
面向切面編程,不修改源代碼給程序動態(tài)統(tǒng)一添加額外功能的一種技術(shù),實現(xiàn)業(yè)務(wù)代碼解耦,應(yīng)用主要體現(xiàn)在事務(wù)處理、日志管理、權(quán)限控制、異常處理等方面,分離功能性需求和非功能性需求,增強代碼的可讀性和可維護性。
日志記錄 事務(wù)管理 權(quán)限驗證 性能監(jiān)控
@Aspect 注解
作用是把當(dāng)前類標(biāo)識為一個切面供容器讀取。
@Before
在方法執(zhí)行前執(zhí)行該方法,并且可以通過(JoinPoint類)獲取請求參數(shù)和方法。
@After
后置通知,在方法執(zhí)行后執(zhí)行??梢酝ㄟ^(JoinPoint類)獲取請求參數(shù)和方法。
@Around
環(huán)繞增強,傳入ProceedingJoinPoint,調(diào)用point.proceed()目標(biāo)方法,相當(dāng)于MethodInterceptor
@Pointcut
標(biāo)注在方法上面,用來定義切入點,格式:@ 注解(value=“表達(dá)標(biāo)簽 (表達(dá)式格式)”) 如:
?@Pointcut("execution(* com.javacode2018.aop.demo9.test1.Service1.*(..))")
- execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
name-pattern(param-pattern) throws-pattern?);
- @annotation用于匹配方法上擁有指定注解的情況。
Guava Limiter限流器
令牌桶算法介紹
- 令牌桶算法則是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌;
- 桶中存放的令牌數(shù)有最大上限,超出之后就被丟棄或者拒絕;
- 當(dāng)流量或者網(wǎng)絡(luò)請求到達(dá)時,每個請求都要獲取一個令牌,如果能夠獲取到,則直接處理,并且令牌桶刪除一個令牌;
- 如果獲取不到,該請求就要被限流,要么直接丟棄,要么在緩沖區(qū)等待。
Limiter API介紹
?// 創(chuàng)建令牌桶,設(shè)置生成令牌速度 ?RateLimiter.create(5); ?// 獲取令牌,如果還沒有到達(dá)接受下一個請求的時間點,就繼續(xù)等待 ?acquire() ?//獲取令牌,如果在我允許的時間范圍內(nèi)獲取不到就不等了,如果能獲取到那我就等著。 ?tryAcquire()
總結(jié)
1、通過自定義注解實現(xiàn)接口限流配置和標(biāo)記;
2、通過Spring AOP 切面編程實現(xiàn)限流邏輯,與業(yè)務(wù)代碼解耦;
3、通過Guava Limiter優(yōu)雅限流。