Java RPC框架如何實(shí)現(xiàn)客戶端限流配置
關(guān)鍵資源
關(guān)鍵資源總是有限的,也就意味著處理能力也有限,所以當(dāng)面對(duì)大量業(yè)務(wù)時(shí),為了保障自己能夠有序的提供服務(wù)最經(jīng)濟(jì)的做法就是限制同一時(shí)間處理的事務(wù)數(shù)。比如銀行的工作人員,一個(gè)工作人員同時(shí)只能為一個(gè)客戶服務(wù),來(lái)多了根本處理不了,不光是一種浪費(fèi)而且有可以造成混亂的局面導(dǎo)致工作人員無(wú)法工作。
網(wǎng)絡(luò)請(qǐng)求漏斗
越上層的服務(wù)器處理的事務(wù)越輕,應(yīng)付請(qǐng)求的能力也越強(qiáng),也就意味著同一請(qǐng)求越上層處理時(shí)間越短。為了有效的保護(hù)下層服務(wù)器,就需要對(duì)發(fā)送給下層的請(qǐng)求量做限流,在下層服務(wù)器可接受的范圍內(nèi)。否則就可能會(huì)出現(xiàn)下層服務(wù)器資源耗盡而無(wú)法正常提供服務(wù)的情況。
限流場(chǎng)景服務(wù)端限流
如果在服務(wù)端做限流,無(wú)論有多少個(gè)客戶端,總的提供能力是固定的(感謝@ xuanbg提出的評(píng)論,指出服務(wù)端也可以對(duì)客戶端做精準(zhǔn)的判斷,后續(xù)我再想想實(shí)現(xiàn)方案),所以不會(huì)因?yàn)榭蛻舳藬?shù)量過(guò)多而導(dǎo)致資源不足,因?yàn)樘幚聿贿^(guò)來(lái)的請(qǐng)求會(huì)被阻塞等待獲取資源。
缺點(diǎn)
缺點(diǎn)也比較明顯,由于服務(wù)提供者整體設(shè)置了最大限流數(shù),此時(shí)所有的客戶端共享同一份限流數(shù)據(jù),那么有可能導(dǎo)致有的服務(wù)能分配到資源有些服務(wù)請(qǐng)求分配不到資源導(dǎo)致無(wú)法請(qǐng)求的情況。
客戶端限流
客戶端限流解決上服務(wù)端限流提到的問(wèn)題,它能保證每個(gè)客戶端都能得到響應(yīng)。但是從其它方面考慮,必須針對(duì)不同的客戶端做不同的限流策略:
請(qǐng)求量大,但時(shí)效性不高,此時(shí)將限流數(shù)控制小一些會(huì)比較合適請(qǐng)求量大,但時(shí)效性高,此時(shí)將限流數(shù)適當(dāng)調(diào)高響應(yīng)時(shí)間長(zhǎng),即慢接口,適當(dāng)降低主流業(yè)務(wù),核心業(yè)務(wù),適當(dāng)調(diào)高非主流業(yè)務(wù),適當(dāng)降低......
缺點(diǎn)
如果客戶端的數(shù)量不固定,那么有可能導(dǎo)致客戶端數(shù)量過(guò)多造成大量請(qǐng)求打到服務(wù)端導(dǎo)致處理不了的結(jié)果,所以需要嚴(yán)格監(jiān)控客戶端的調(diào)用情況。
配置復(fù)雜,需要針對(duì)每個(gè)客戶端做相對(duì)精準(zhǔn)的判斷
RPC實(shí)現(xiàn)
限流
這里指的限流是指每秒從客戶端提交到服務(wù)端的請(qǐng)求數(shù)量。
服務(wù)引用注解上增加限流
public @interface RpcReference { boolean isSync() default true; /** * 客戶端最大并發(fā)數(shù) * @return */ int maxExecutesCount() default 10; }
創(chuàng)建動(dòng)態(tài)代理時(shí)將限流參數(shù)傳遞到服務(wù)端
需要修改RpcProxy類,構(gòu)造函數(shù)中增加服務(wù)引用注解參數(shù),然后在invoke方法中從服務(wù)引用注解中獲取限流參數(shù)傳遞給request對(duì)象。
public RpcProxy(Class<T> clazz,ReferenceConfig referenceConfig,RpcReference reference) { this.clazz = clazz; this.referenceConfig=referenceConfig; this.reference=reference; this.isSync=reference.isSync(); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ... if (this.reference != null) { request.setMaxExecutesCount(this.reference.maxExecutesCount()); } ... }
AbstractInvoker修改buildRpcInvocation方法
從request對(duì)象中獲取限流參數(shù),傳遞給RpcInvocation對(duì)象。
public interface RpcInvocation { ... int getMaxExecutesCount(); }
AccessLimitFilter修改令牌管理器
按接口分配令牌管理器,令牌管理器存儲(chǔ)在map中共享。如果未初始化則進(jìn)行令牌管理器的初始化,如果已經(jīng)初始化則直接申請(qǐng)令牌。
public RpcInvocation buildRpcInvocation(RpcRequest request){ RpcInvocation rpcInvocation=new RpcInvocation() { ... @Override public int getMaxExecutesCount() { return request.getMaxExecutesCount(); } }; return rpcInvocation; }
修改invoke方法
將invocation參數(shù)傳遞給acquire方法。
public Object invoke(RpcInvoker invoker, RpcInvocation invocation) { logger.info("before acquire,"+new Date()); AccessLimitManager.acquire(invocation); Object rpcResponse=invoker.invoke(invocation); logger.info("after acquire,"+new Date()); return rpcResponse; }
客戶端服務(wù)引用配置限流
這里配置每秒一個(gè)請(qǐng)求
@RpcReference(maxExecutesCount = 1) private ProductService productService;
執(zhí)行結(jié)果
如下圖所示,每次請(qǐng)求相隔了一秒,達(dá)到了限流請(qǐng)求的目的。
支持方法級(jí)限流
以上只支持客戶端接口級(jí)別的限流配置,可以再單獨(dú)創(chuàng)建一個(gè)方法級(jí)的注解來(lái)配置相關(guān)參數(shù)。
支持服務(wù)端限流
服務(wù)端限流盡管有它的缺點(diǎn),但為了更好的保護(hù)服務(wù)提供者,需要結(jié)合多種業(yè)務(wù)場(chǎng)景來(lái)配合客戶端限流一起完善,取長(zhǎng)補(bǔ)短共同發(fā)揮作用。
本文源碼
https://github.com/jiangmin168168/jim-framework
文中代碼是依賴上述項(xiàng)目的,如果有不明白的可下載源碼
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot2.7.14整合redis7的詳細(xì)過(guò)程
這篇文章主要介紹了SpringBoot2.7.14整合redis7的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-10-10Java中幾種常用數(shù)據(jù)庫(kù)連接池的使用
數(shù)據(jù)庫(kù)連接池在編寫應(yīng)用服務(wù)是經(jīng)常需要用到的模塊,太過(guò)頻繁的連接數(shù)據(jù)庫(kù)對(duì)服務(wù)性能來(lái)講是一個(gè)瓶頸,使用緩沖池技術(shù)可以來(lái)消除這個(gè)瓶頸,本文就來(lái)介紹Java常見的幾種,感興趣的可以了解一下2021-05-05spring cloud feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用服務(wù)傳輸文件的方法
這篇文章主要介紹了spring cloud feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用服務(wù)傳輸文件的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09string類和LocalDateTime的相互轉(zhuǎn)換方式
這篇文章主要介紹了string類和LocalDateTime的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗問(wèn)題
這篇文章主要介紹了實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12