一敛惊,Zuul的應(yīng)用場(chǎng)景
Zuul是Netflix基于JVM的路由器和服務(wù)器端負(fù)載均衡器蚪腋。
Zuul可以通過(guò)加載動(dòng)態(tài)過(guò)濾機(jī)制扣癣,從而實(shí)現(xiàn)以下各項(xiàng)功能:
驗(yàn)證與安全保障:識(shí)別面向各類資源的驗(yàn)證要求并拒絕那些與要求不符的請(qǐng)求即寒。
審查與監(jiān)控:在邊緣位置追蹤有意義數(shù)據(jù)及統(tǒng)計(jì)結(jié)果橡淆,從而為我們帶來(lái)準(zhǔn)確的生產(chǎn)狀態(tài)結(jié)論。
動(dòng)態(tài)路由:以動(dòng)態(tài)方式根據(jù)需要將請(qǐng)求路由至不同后端集群母赵。
壓力測(cè)試:逐漸增加指向集群的負(fù)載流量逸爵,從而計(jì)算性能水平。
負(fù)載分配:為每一種負(fù)載類型分配對(duì)應(yīng)容量凹嘲,并棄用超出限定值的請(qǐng)求师倔。
靜態(tài)響應(yīng)處理:在邊緣位置直接建立部分響應(yīng),從而避免其流入內(nèi)部集群周蹭。
多區(qū)域彈性::跨越AWS區(qū)域進(jìn)行請(qǐng)求路由趋艘,旨在實(shí)現(xiàn)ELB使用多樣化并保證邊緣位置與使用者盡可能接近疲恢。
Zuul的規(guī)則引擎允許任何JVM語(yǔ)言編寫(xiě)規(guī)則和過(guò)濾器,內(nèi)置支持Java和Groovy瓷胧。
二显拳,Zuul的配置文件詳解
1,超時(shí)時(shí)間配置
Spring Cloud因?yàn)檎狭藌uul搓萧,ribbon萎攒,hystrix,所以超時(shí)時(shí)間也比較復(fù)雜矛绘,到底使用哪個(gè)超時(shí)時(shí)間配置耍休,我們來(lái)看一下。
zuul的超時(shí)時(shí)間配置:
zuul.host.socket-timeout-millis
zuul.host.connect-timeout-millis
ribbon的超時(shí)時(shí)間配置:
ribbon.ConnectTimeout
ribbon.ReadTimeout
hystrix的超時(shí)時(shí)間配置:
hystrix.command.default.execution.
isolation.thread.timeoutInMillisecond
如果我們既設(shè)置了ribbon的超時(shí)時(shí)間货矮,又設(shè)置了hystrix的超時(shí)時(shí)間羊精,那么zuul最終會(huì)取較小的那個(gè)值。
2囚玫,host最大連接數(shù)配置
zuul.host.maxTotalConnections:最大連接數(shù)喧锦。默認(rèn)值是200,我們項(xiàng)目配置的是2000抓督。
zuul.host.maxPreRouteConnections:每個(gè)路由的最大連接數(shù)燃少。默認(rèn)20,我們項(xiàng)目配置的是500铃在。
3阵具,路由配置
zuul.routes.微服務(wù).path:請(qǐng)求轉(zhuǎn)發(fā)路徑,也就是說(shuō)zuul會(huì)把帶有當(dāng)前的請(qǐng)求轉(zhuǎn)發(fā)到對(duì)應(yīng)的名稱為serviceId的微服務(wù)上定铜。
zuul.routes.微服務(wù).serviceId:微服務(wù)的唯一標(biāo)識(shí)阳液。
zuul.routes.微服務(wù).stripPrefix:是否去掉前綴。這個(gè)配置是配合zuul.prefix來(lái)使用的揣炕,如果我們?cè)O(shè)置了前綴帘皿,可以通過(guò)設(shè)置stripPrefix=true來(lái)自動(dòng)去掉前綴。
zuul.routes.xxx.url:配置反向代理畸陡。
zuul.routes.微服務(wù).sensitive-headers:過(guò)濾掉客戶端附帶的headers相關(guān)屬性鹰溜。Zuul默認(rèn)會(huì)過(guò)濾掉下面三個(gè)屬性:
Cookies
Set-Cookie
Authorization
具體可以參考源碼:ZuulProperties
zuul.routes.微服務(wù).ignored-headers:
具體可以參考源碼:ZuulProperties。
4丁恭,hystrix相關(guān)配置
#hystrix的隔離策略
hystrix.command.default.execution.isolation.strategy=THREAD
Hystrix的隔離策略有兩種:分別是線程隔離和信號(hào)量隔離曹动。
THREAD(線程隔離):使用該方式,HystrixCommand將會(huì)在單獨(dú)的線程上執(zhí)行涩惑,并發(fā)請(qǐng)求受線程池中線程數(shù)量的限制仁期。
SEMAPHORE(信號(hào)量隔離):使用該方式,HystrixCommand將會(huì)在調(diào)用線程上執(zhí)行竭恬,開(kāi)銷相對(duì)較小跛蛋,并發(fā)請(qǐng)求受信號(hào)量的個(gè)數(shù)的限制。
Hystrix中默認(rèn)并且推薦使用線程隔離痊硕,因?yàn)檫@種方式有一個(gè)除網(wǎng)絡(luò)超時(shí)以外的額外保護(hù)層赊级。
一般來(lái)說(shuō),只有當(dāng)調(diào)用負(fù)載非常高時(shí)(例如每個(gè)實(shí)例每秒調(diào)用數(shù)百次)才需要使用信號(hào)量隔離岔绸,因?yàn)檫@種場(chǎng)景下使用THREAD開(kāi)銷會(huì)比較高理逊。信號(hào)量隔離一般僅適用于非網(wǎng)絡(luò)調(diào)用的隔離。
#設(shè)置HystrixCommand的執(zhí)行是否有超時(shí)限制盒揉。
hystrix.command.default.execution.timeout.enabled=false
#等待hystrix命令執(zhí)行的超時(shí)時(shí)間
hystrix.command.default.execution.isolation.thread.timeoutInMillisecond=90000
設(shè)置調(diào)用者等待命令執(zhí)行的超時(shí)限制晋被,超過(guò)此時(shí)間,HystrixCommand被標(biāo)記為T(mén)IMEOUT刚盈,并執(zhí)行回退邏輯羡洛。
注意:超時(shí)會(huì)作用在HystrixCommand.queue(),即使調(diào)用者沒(méi)有調(diào)用get()去獲得Future對(duì)象藕漱。
#HystrixCommand執(zhí)行方法允許的最大請(qǐng)求數(shù)欲侮。
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequest=200
設(shè)置當(dāng)使用ExecutionIsolationStrategy.SEMAPHORE時(shí),HystrixCommand執(zhí)行方法允許的最大請(qǐng)求數(shù)肋联。如果達(dá)到最大并發(fā)數(shù)時(shí)威蕉,后續(xù)請(qǐng)求會(huì)被拒絕。信號(hào)量應(yīng)該是容器(比如Tomcat)線程池一小部分橄仍,不能等于或者略小于容器線程池大小韧涨,否則起不到保護(hù)作用。
#設(shè)置斷路器是否生效
hystrix.command.default.circuitBreaker.enabled=true
#是否強(qiáng)制打開(kāi)斷路器
hystrix.command.default.circuitBreaker.forceOpen=false
如果該屬性設(shè)置為true侮繁,強(qiáng)制斷路器進(jìn)入打開(kāi)狀態(tài)氓奈,將會(huì)拒絕所有的請(qǐng)求。該屬性優(yōu)先級(jí)比circuitBreaker.forceClosed高鼎天。
#是否強(qiáng)制關(guān)閉斷路器
hystrix.command.default.circuitBreaker.forceClosed=false
如果該屬性設(shè)置為true舀奶,強(qiáng)制斷路器進(jìn)入關(guān)閉狀態(tài),將會(huì)允許所有的請(qǐng)求斋射,無(wú)視錯(cuò)誤率育勺。
#線程池核心線程數(shù)
hystrix.threadpool.default.coreSize=2000
這里的coreSize和ThreadPoolExecutor的corePoolSize是不同的概念。hystrix會(huì)對(duì)請(qǐng)求進(jìn)行隔離罗岖,這個(gè)隔離是通過(guò)線程池來(lái)實(shí)現(xiàn)的涧至。hystrix會(huì)根據(jù)調(diào)用的服務(wù),對(duì)線程池進(jìn)行重新劃分桑包,這個(gè)coreSize是hystrix劃分的線程池的核心線程數(shù)南蓬。
#最大信號(hào)量
zuul.semaphore.max-semaphore=5000
設(shè)置當(dāng)使用ExecutionIsolationStrategy.SEMAPHORE時(shí),信號(hào)量的最大值。
三赘方,Zuul的隔離模式
準(zhǔn)確的說(shuō)烧颖,Zuul沒(méi)有隔離模式,我們這里的隔離模式本質(zhì)上是Hystrix的隔離模式窄陡,在Spring Cloud體系中炕淮,Zuul默認(rèn)整合了Hystrix。
在Hystrix的jar包下跳夭,有一個(gè)HystrixCommandProperties涂圆,這個(gè)類中定義了2個(gè)隔離級(jí)別:SEMAPHORE和THREAD,默認(rèn)使用SEMAPHORE币叹。
SEMAPHORE:信號(hào)量隔離級(jí)別润歉。
THREAD:線程池隔離級(jí)別。
這2種隔離級(jí)別有何區(qū)別呢颈抚?
THREAD(線程隔離):使用該方式踩衩,HystrixCommand將會(huì)在單獨(dú)的線程上執(zhí)行,并發(fā)請(qǐng)求受線程池中線程數(shù)量的限制邪意。
SEMAPHORE(信號(hào)量隔離):使用該方式九妈,HystrixCommand將會(huì)在調(diào)用線程上執(zhí)行,開(kāi)銷相對(duì)較小雾鬼,并發(fā)請(qǐng)求受信號(hào)量的個(gè)數(shù)的限制萌朱。
Hystrix中默認(rèn)并且推薦使用線程隔離,因?yàn)檫@種方式有一個(gè)除網(wǎng)絡(luò)超時(shí)以外的額外保護(hù)層策菜。
一般來(lái)說(shuō)晶疼,只有當(dāng)調(diào)用負(fù)載非常高時(shí)(例如每個(gè)實(shí)例每秒調(diào)用數(shù)百次)才需要使用信號(hào)量隔離,因?yàn)檫@種場(chǎng)景下使用THREAD開(kāi)銷會(huì)比較高又憨。信號(hào)量隔離一般僅適用于非網(wǎng)絡(luò)調(diào)用的隔離翠霍。
四,Zuul架構(gòu)圖
這里簡(jiǎn)單總結(jié)一下Zuul的工作原理蠢莺。
1寒匙,ZuulServlet
ZuulServlet是Zuul的入口。ZuulServlet繼承了抽象類HttpServlet躏将,把HttpServlet包裝成ZuulServlet锄弱。ZuulServlet實(shí)現(xiàn)了GenericServlet的init()方法,并且實(shí)現(xiàn)了HttpServlet的service()方法祸憋。
也就是說(shuō)会宪,ZuulServlet具備了為Zuul提供服務(wù)的能力,通過(guò)ZuulServlet.service()蚯窥,ZuulServlet可以開(kāi)啟Zuul服務(wù)了掸鹅!
2塞帐,ZuulRunner
ZuulServlet最終會(huì)把請(qǐng)求交給ZuulRunner,由ZuulRunner來(lái)執(zhí)行具體的邏輯巍沙。
ZuulRunner做了什么呢葵姥?ZuulRunner拿到RequestContext,然后設(shè)置了HttpServletRequest和HttpServletResponse就完事了赎瞎。然后把請(qǐng)求交給FilterProcessor牌里。
3颊咬,F(xiàn)ilterProcessor
FilterProcessor是過(guò)濾器的最終執(zhí)行者务甥。
4,F(xiàn)ilterLoader
FilterLoader借助FilterRegistry喳篇,實(shí)現(xiàn)了獲取查詢和新增過(guò)濾器的功能敞临。有一點(diǎn)需要注意,如果拿到的ZuulFilter為空麸澜,F(xiàn)ilterLoader會(huì)嘗試使用GroovyCompiler加載ZuulFilter挺尿。