亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring?Cloud?Hystrix原理與注意事項(xiàng)小結(jié)

 更新時(shí)間:2025年03月03日 14:06:36   作者:張彥峰ZYF  
本文介紹了Hystrix的基本概念、工作原理以及其在實(shí)際開發(fā)中的應(yīng)用方式,通過(guò)對(duì)Hystrix的深入學(xué)習(xí),開發(fā)者可以在分布式系統(tǒng)中實(shí)現(xiàn)精細(xì)的錯(cuò)誤處理機(jī)制,并能夠及時(shí)響應(yīng)系統(tǒng)中的異常,避免服務(wù)的連鎖崩潰,感興趣的朋友一起看看吧

Spring Cloud Hystrix是一個(gè)強(qiáng)大的容錯(cuò)框架,基于Netflix Hystrix開發(fā),能夠有效隔離服務(wù)的依賴,避免單個(gè)服務(wù)的失敗影響到整個(gè)系統(tǒng)。它通過(guò)熔斷器、降級(jí)機(jī)制、線程池隔離等手段,在面對(duì)服務(wù)故障時(shí),依然能夠確保系統(tǒng)能夠優(yōu)雅地降級(jí),并保持服務(wù)的可用性。此外,Hystrix還支持實(shí)時(shí)監(jiān)控和告警,幫助開發(fā)者及時(shí)發(fā)現(xiàn)和處理系統(tǒng)中的問(wèn)題。

本篇文章將對(duì)Spring Cloud Hystrix進(jìn)行剖析,介紹其設(shè)計(jì)理念、工作原理以及如何在實(shí)際項(xiàng)目中使用它來(lái)實(shí)現(xiàn)服務(wù)的容錯(cuò)和高可用性。希望通過(guò)本文的講解,能夠幫助讀者深入理解Hystrix的核心功能和配置,掌握其在分布式系統(tǒng)中的應(yīng)用,為構(gòu)建高可用的微服務(wù)架構(gòu)打下堅(jiān)實(shí)的基礎(chǔ)。

一、Spring Cloud Hystrix概述和設(shè)計(jì)目標(biāo)

(一)Spring Cloud Hystrix基本概述

在軟件架構(gòu)領(lǐng)域,容錯(cuò)特指容忍并防范局部錯(cuò)誤,不讓這種局部錯(cuò)誤不斷擴(kuò)大。我們?cè)谧R(shí)別風(fēng)險(xiǎn)領(lǐng)域,風(fēng)險(xiǎn)可以分為已知風(fēng)險(xiǎn)和未知風(fēng)險(xiǎn),容錯(cuò)直接應(yīng)對(duì)的就是已知風(fēng)險(xiǎn),這就要求針對(duì)的場(chǎng)景是:系統(tǒng)之間調(diào)用延時(shí)超時(shí)、線程的數(shù)量急劇飆升導(dǎo)致CPU使用率升高、集群服務(wù)器磁盤被打滿等等。面對(duì)容錯(cuò),我們一般都會(huì)要求提供降級(jí)方案,而且強(qiáng)調(diào)不可進(jìn)行暴力降級(jí)(比如把整個(gè)論壇功能降掉直接給用戶展現(xiàn)一個(gè)大白板),而是將一部分?jǐn)?shù)據(jù)緩存起來(lái),也就是要有拖底數(shù)據(jù)。

在一個(gè)分布式系統(tǒng)中,必然會(huì)有部分系統(tǒng)的調(diào)用會(huì)失敗。Hystrix是一個(gè)通過(guò)添加超時(shí)容錯(cuò)和失敗容錯(cuò)邏輯來(lái)幫助你控制這些分布式系統(tǒng)的交互。Hystrix通過(guò)隔離服務(wù)之間的訪問(wèn),阻止他們之間的級(jí)聯(lián)故障以及提供后背選項(xiàng)來(lái)實(shí)現(xiàn)進(jìn)行丟底方案,從而提高系統(tǒng)的整體彈性。

Hystrix對(duì)應(yīng)的中文名字是“豪豬”,豪豬周身長(zhǎng)滿了刺,能保護(hù)自己不受天敵的傷害,代表了一種防御機(jī)制,Hystrix提供了熔斷、隔離、Fallback、cache、監(jiān)控等功能,能夠在一個(gè)、或多個(gè)依賴同時(shí)出現(xiàn)問(wèn)題時(shí)保證系統(tǒng)依然可用。

查看Hytrix官網(wǎng)有如下描述:

Introduction:
Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, 
services and 3rd party libraries, 
stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

大意是:Hystrix是一個(gè)延遲和容錯(cuò)庫(kù),旨在隔離遠(yuǎn)程系統(tǒng)、服務(wù)和第三方庫(kù),阻止級(jí)聯(lián)故障,在復(fù)雜的分布式系統(tǒng)中實(shí)現(xiàn)恢復(fù)能力。

(二)Spring Cloud Hystrix概述設(shè)計(jì)目標(biāo)

查看Hystrix官網(wǎng)Home · Netflix/Hystrix Wiki · GitHub中對(duì)設(shè)計(jì)目標(biāo)有如下描述:

Hystrix is designed to do the following:
1.Give protection from and control over latency and failure from dependencies accessed 
(typically over the network) via third-party client libraries.
2.Stop cascading failures in a complex distributed system.
3.Fail fast and rapidly recover.
4.Fallback and gracefully degrade when possible.
5.Enable near real-time monitoring, alerting, and operational control.

翻譯如下:

  • 1.通過(guò)客戶端庫(kù)對(duì)延遲和故障進(jìn)行保護(hù)和控制。
  • 2.在一個(gè)復(fù)雜分布式系統(tǒng)中防止級(jí)聯(lián)故障。
  • 3.快速失敗和迅速恢復(fù)。
  • 4.在合理情況下回退和優(yōu)雅降級(jí)。
  • 5.開啟近實(shí)時(shí)監(jiān)控、告警和操作控制。

二、Spring Cloud Hystrix解決的主要內(nèi)容

(一)隔離(線程池隔離和信號(hào)量隔離)

在微服務(wù)架構(gòu)中,要求服務(wù)的容錯(cuò)隔離,以及對(duì)應(yīng)的回退降級(jí)限流方案理論,我們?cè)谝韵虏┛椭幸呀?jīng)初步提到:微服務(wù)架構(gòu)服務(wù)可靠性分析

隔離的基本要求是:限制調(diào)用分布式服務(wù)的資源使用,某一個(gè)調(diào)用的服務(wù)出現(xiàn)問(wèn)題不會(huì)影響其他服務(wù)調(diào)用。Spring Cloud Hystrix下針對(duì)隔離主要指的是線程池隔離和信號(hào)量隔離。如下圖所示,可以很明顯的說(shuō)明信號(hào)量隔離和線程池隔離的主要區(qū)別:線程池方式下,業(yè)務(wù)請(qǐng)求線程和執(zhí)行依賴的服務(wù)線程不是同一個(gè)線程;信號(hào)量方式下業(yè)務(wù)請(qǐng)求線程和執(zhí)行依賴的線程是同一個(gè)線程。

1.線程和線程池

線程隔離指每個(gè)服務(wù)都為一個(gè)個(gè)獨(dú)立的線程組,當(dāng)某個(gè)服務(wù)出現(xiàn)問(wèn)題時(shí),不會(huì)導(dǎo)致整個(gè)服務(wù)癱瘓。由于線程隔離會(huì)帶來(lái)線程開銷,有些場(chǎng)景(比如無(wú)網(wǎng)絡(luò)請(qǐng)求場(chǎng)景)可能會(huì)因?yàn)橛瞄_銷換隔離得不償失,為此hystrix提供了信號(hào)量隔離,當(dāng)服務(wù)的并發(fā)數(shù)大于信號(hào)量閾值時(shí)將進(jìn)入fallback。

如下圖,客戶端(第三方,網(wǎng)絡(luò)調(diào)用等)依賴和請(qǐng)求線程運(yùn)行在不同的線程上,可以將他們從調(diào)用線程隔離開來(lái),這樣調(diào)用者就可以從一個(gè)耗時(shí)太長(zhǎng)的依賴中隔離,也可以為不同的請(qǐng)求開啟不同的線程池,彼此之間不相互干擾。

傳統(tǒng)上,我們?cè)趯?shí)現(xiàn)線程池隔離的手段上,一般有以下兩種方式:

  • 方式一:使用一個(gè)大的線程池,固定線程池的大小,比如1000,通過(guò)權(quán)重的思路為某個(gè)方法分配一個(gè)固定大小的線程數(shù),比如為某個(gè)方法請(qǐng)求分配了10個(gè)線程,按照實(shí)現(xiàn)方式有“保守型”和“限制性”,具體見以后博客中和github中的代碼舉例。
  • 方式二:利用ConcurrentHashMap來(lái)存儲(chǔ)線程池,key是方法名,值是每個(gè)方法對(duì)應(yīng)的一個(gè)ThreadPool。當(dāng)請(qǐng)求到來(lái)的時(shí)候,我們獲取方法名,然后直接從Map對(duì)象中取到響應(yīng)的線程池去處理。

對(duì)于方法一而言,嚴(yán)格意義上講,它并不屬于線程池隔離,因?yàn)樗挥幸粋€(gè)公共的線程池,然后來(lái)讓大家瓜分,不過(guò)也達(dá)到了隔離的效果。在Spring Cloud Hystrix的線程池隔離上,我們使用的是方式二。對(duì)于以上兩種方式,線程池的粒度都是作用在方法上,我們可以結(jié)合實(shí)際情況也可以按組來(lái)分。

線程隔離的好處

整個(gè)應(yīng)用在客戶端調(diào)用失效的情況下也能健康的運(yùn)行,線程池能夠保證這個(gè)線程的失效不會(huì)影響應(yīng)用的運(yùn)行。當(dāng)失效的客戶端調(diào)用回復(fù)的時(shí)候,這個(gè)線程池也會(huì)被清理并且應(yīng)用會(huì)立馬回復(fù)健康,比tomcat那種長(zhǎng)時(shí)間的恢復(fù)要好很多。簡(jiǎn)而言之,線程隔離能夠允許在不引起中斷的情況下優(yōu)雅的處理第三方調(diào)用的各種問(wèn)題。

線程隔離的缺點(diǎn)

主要缺點(diǎn)是增加了上下文切換的開銷,每個(gè)執(zhí)行都涉及到隊(duì)列,調(diào)度和上下文切換。不過(guò)NetFix在設(shè)計(jì)這個(gè)系統(tǒng)的時(shí)候,已經(jīng)決定接受這筆開銷,以換取他的好處。對(duì)于不依賴網(wǎng)絡(luò)訪問(wèn)的服務(wù),比如只依賴內(nèi)存緩存,就不適合用線程池隔離技術(shù),而是采用信號(hào)量隔離。

2.信號(hào)量隔離(Semaphores)

可以使用信號(hào)量(或者計(jì)數(shù)器)來(lái)限制當(dāng)前依賴調(diào)用的并發(fā)數(shù),而不是使用線程池或者隊(duì)列。如果客戶端是可信的,且能快速返回,可以使用信號(hào)量來(lái)代替線程隔離,降低開銷。信號(hào)量的大小可以動(dòng)態(tài)調(diào)節(jié),線程池卻不行。

HystrixCommand和HystrixObserverCommand提供信號(hào)量隔離在下面兩個(gè)地方:

  • Fallback:當(dāng)Hystrix檢索fallback的時(shí)候,他心總是調(diào)用tomcat線程上執(zhí)行此操作
  • 如果你設(shè)置execution.isolation.strategy為SEMAPHORE的時(shí)候,Hystrix會(huì)使用信號(hào)量代替線程池去限制當(dāng)前調(diào)用Command的并發(fā)數(shù)。

對(duì)于不依賴網(wǎng)絡(luò)訪問(wèn)的服務(wù),就不適合使用線程池隔離,而是采用信號(hào)量隔離。

(二)優(yōu)雅的降級(jí)機(jī)制

超時(shí)降級(jí)、資源不足時(shí)(線程或信號(hào)量)降級(jí),降級(jí)總之是一種退而求其次的方式,所謂降級(jí),就是指在Hystrix執(zhí)行費(fèi)核心鏈路功能失敗的情況下,我們應(yīng)該如何返回的問(wèn)題,根據(jù)業(yè)務(wù)場(chǎng)景的不同,一般采用以下兩種模式進(jìn)行降級(jí):

  • 第一種:(最常用)如果服務(wù)失敗,則我們通過(guò)fallback進(jìn)行降級(jí),返回靜態(tài)值。
  • 第二種:調(diào)用備選方案

降級(jí)會(huì)退的方案有很多,以上只是初步的建議,具體降級(jí)回退方案如:Fail Fast(快速失敗)、Fail Silent(無(wú)聲失?。?、Fallback:Static(返回默認(rèn)值)、Fallback:Stubbed(自己組裝一個(gè)值返回)、Fallback:Cache via Network(利用遠(yuǎn)程緩存)、Primary + Secondary with fallback(主次方式回退),其基本的實(shí)現(xiàn)在相關(guān)功能由介紹,建議進(jìn)行擴(kuò)展學(xué)習(xí)。

這里需要注意回退處理方式不適合的場(chǎng)景,如以下三種場(chǎng)景我們不可以使用回退處理:

  • 寫操作
  • 批處理
  • 計(jì)算

(三)熔斷器

當(dāng)失敗率達(dá)到閥值自動(dòng)觸發(fā)降級(jí)(如因網(wǎng)絡(luò)故障/超時(shí)造成的失敗率高),熔斷器觸發(fā)的快速失敗會(huì)進(jìn)行快速恢復(fù),類似于電閘。下圖是基本源碼中的一個(gè)處理流程圖:

斷路器打開還是關(guān)閉的步驟如下

1.假定請(qǐng)求的量超過(guò)預(yù)定的閾值(circuitBreakerRequestVolumeThreshold)
2.再假定錯(cuò)誤百分比超過(guò)了設(shè)定的百分比(circuitBreakerErrorThresholdPercentage)
3.斷路器會(huì)從close狀態(tài)到open狀態(tài)
4.當(dāng)打開的狀態(tài),會(huì)短路所有針對(duì)該斷路器的請(qǐng)求
5.過(guò)了一定時(shí)間(circuitBreakerSleepWindowInMilliseconds(短路超過(guò)一定時(shí)間會(huì)重新去請(qǐng)求)),下一個(gè)請(qǐng)求將通過(guò),不會(huì)被短路(當(dāng)前是half-open狀態(tài))。如果這個(gè)請(qǐng)求失敗了,則斷路器在睡眠窗口期間返回open狀態(tài),如果請(qǐng)求成功,則斷路器返回close狀態(tài),并重新回到第一步邏輯判斷。

(四)緩存

提供了請(qǐng)求緩存、請(qǐng)求合并實(shí)現(xiàn)。

1.Hystrix緩存策略的命令執(zhí)行流程                       

2.請(qǐng)求合并實(shí)現(xiàn)

為什么要進(jìn)行請(qǐng)求合并?舉個(gè)例子,有個(gè)礦山,每過(guò)一段時(shí)間都會(huì)生產(chǎn)一批礦產(chǎn)出來(lái)(質(zhì)量為卡車載重量的1/100),卡車可以一等到礦產(chǎn)生產(chǎn)出來(lái)就馬上運(yùn)走礦產(chǎn),也可以等到卡車裝滿再運(yùn)走礦產(chǎn),

前者一次生產(chǎn)對(duì)應(yīng)卡車一次往返,卡車需要往返100次,而后者只需要往返一次,可以大大減少卡車往返次數(shù)。顯而易見,利用請(qǐng)求合并可以減少線程和網(wǎng)絡(luò)連接,開發(fā)人員不必單獨(dú)提供一個(gè)批量請(qǐng)求接口就可以完成批量請(qǐng)求。

 在Hystrix中進(jìn)行請(qǐng)求合并也是要付出一定代價(jià)的,請(qǐng)求合并會(huì)導(dǎo)致依賴服務(wù)的請(qǐng)求延遲增高,延遲的最大值是合并時(shí)間窗口的大小,默認(rèn)為10ms,當(dāng)然我們也可以通過(guò)hystrix.collapser.default.timerDelayInMilliseconds屬性進(jìn)行修改,如果請(qǐng)求一次依賴服務(wù)的平均響應(yīng)時(shí)間是20ms,那么最壞情況下(合并窗口開始是請(qǐng)求加入等待隊(duì)列)這次請(qǐng)求響應(yīng)時(shí)間就會(huì)變成30ms。在Hystrix中對(duì)請(qǐng)求進(jìn)行合并是否值得主要取決于Command本身,高并發(fā)度的接口通過(guò)請(qǐng)求合并可以極大提高系統(tǒng)吞吐量,從而基本可以忽略合并時(shí)間窗口的開銷,反之,并發(fā)量較低,對(duì)延遲敏感的接口不建議使用請(qǐng)求合并。

請(qǐng)求合并的流程圖如下:                  

可以看出Hystrix會(huì)把多個(gè)Command放入Request隊(duì)列中,一旦滿足合并時(shí)間窗口周期大小,Hystrix會(huì)進(jìn)行一次批量提交,進(jìn)行一次依賴服務(wù)的調(diào)用,通過(guò)充寫HystrixCollapser父類的mapResponseToRequests方法,將批量返回的請(qǐng)求分發(fā)到具體的每次請(qǐng)求中。

(五)支持實(shí)時(shí)監(jiān)控、報(bào)警、控制(修改配置)

通過(guò)儀表盤等進(jìn)行統(tǒng)計(jì)后,從而進(jìn)行實(shí)時(shí)監(jiān)控、報(bào)警、控制,最終依據(jù)這些來(lái)修改配置,得到最佳的選擇。

三、Spring Cloud Hystrix工作流程介紹

基本流程圖如下:

1.創(chuàng)建HystrixCommand或者HystrixObservableCommand對(duì)象。用來(lái)表示對(duì)以來(lái)服務(wù)的請(qǐng)求操作。從命名就能看的出來(lái),使用的是命令模式,其中HystrixCommand返回的是單個(gè)操作結(jié)果,HystrixObservableCommand返回多個(gè)結(jié)果
2.命令執(zhí)行,共有4中方法執(zhí)行命令:

  • execute():用戶執(zhí)行,從依賴的服務(wù)里返回單個(gè)結(jié)果或拋出異常
  • queue():異步執(zhí)行,直接返回一個(gè)Future對(duì)象
  • observe():放回observable對(duì)象,代表了多個(gè)結(jié)果,是一個(gè)Hot Observableto
  • Observable():返回Observable對(duì)象,但是是一個(gè) Cold Observable(Hystrix大量的使用了RxJava,想更容易的理解Hystrix的,請(qǐng)自行百度RxJava進(jìn)行閱讀。)

3.結(jié)果是否被緩存。如果已經(jīng)啟用了緩存功能,且被命中,那么緩存就會(huì)直接以O(shè)bservable對(duì)象返回
4.斷路器是否已打開,沒有命中緩存,在執(zhí)行命令前會(huì)檢查斷路器是否已打開:

  • 斷路器已打開,直接執(zhí)行fallback
  • 斷路器關(guān)閉,繼續(xù)往下執(zhí)行

5.線程池And信號(hào)量Or請(qǐng)求隊(duì)列是否已被占滿    如果與該命令有關(guān)的線程池和請(qǐng)求隊(duì)列,或者信號(hào)量已經(jīng)被占滿,就直接執(zhí)行fallback
6.執(zhí)行HystrixObservableCommand.construct () 或 HystrixCommand.run()  方法。如果設(shè)置了當(dāng)前執(zhí)行時(shí)間超過(guò)了設(shè)置的timeout,則當(dāng)前處理線程會(huì)拋出一個(gè)TimeoutyException,如果命令不在自身線程里執(zhí)行,就會(huì)通過(guò)單獨(dú)的計(jì)時(shí)線程來(lái)拋出異常,Hystrix會(huì)直接執(zhí)行fallback邏輯,并忽略run或construct的返回值。
7.計(jì)算斷路器的健康值。
8.fallback處理。
9.返回成功的響應(yīng)。

四、儀表盤講解

Spring Cloud Hystrix Dashboard是一個(gè)可以監(jiān)控HystrixCommand的可視化圖形界面,由于某種原因,如網(wǎng)絡(luò)延遲、服務(wù)故障等,這時(shí)候可以借助dashboard提供的可視化界面監(jiān)控各個(gè)Hystrix執(zhí)行的成功率、調(diào)用成功數(shù)、失敗數(shù)量、最近十分鐘的流量圖等等,根據(jù)這些數(shù)據(jù)我們就可以進(jìn)行錯(cuò)誤排查以及進(jìn)行服務(wù)的優(yōu)化等。Hystrix Dashboard只能對(duì)單個(gè)服務(wù)進(jìn)行監(jiān)控,實(shí)際項(xiàng)目中,服務(wù)通常集群部署,這時(shí)候可以借助Turbine進(jìn)行多個(gè)服務(wù)的監(jiān)控。

(一)監(jiān)控單體應(yīng)用

不管是監(jiān)控單體應(yīng)用還是Turbine集群監(jiān)控,我們都需要一個(gè)Hystrix Dashboard,當(dāng)然我們可以在要監(jiān)控的單體應(yīng)用上繼續(xù)添加功能,讓它也具備儀表盤的功能,但是這樣并不符合我們微服務(wù)的思想,所以,Hystrix儀表盤我還是單獨(dú)創(chuàng)建一個(gè)新的工程專門用來(lái)做Hystrix Dashboard。Hystrix Dashboard儀表盤是根據(jù)系統(tǒng)一段時(shí)間內(nèi)發(fā)生的請(qǐng)求情況來(lái)展示的可視化面板,這些信息時(shí)每個(gè)HystrixCommand執(zhí)行過(guò)程中的信息,這些信息是一個(gè)指標(biāo)集合和具體的系統(tǒng)運(yùn)行情況。如Hystrix Dashboard界面圖:       

輸入相關(guān)數(shù)據(jù),得到如下儀表盤:    

(二)Turbine集群監(jiān)控

在實(shí)際應(yīng)用中,我們要監(jiān)控的應(yīng)用往往是一個(gè)集群,這個(gè)時(shí)候我們就得采取Turbine集群監(jiān)控了。Turbine有一個(gè)重要的功能就是匯聚監(jiān)控信息,并將匯聚到的監(jiān)控信息提供給Hystrix Dashboard來(lái)集中展示和監(jiān)控。

在實(shí)際項(xiàng)目中,這種實(shí)時(shí)監(jiān)控有點(diǎn)耗性能,通常采用消息中間件如RabbitMQ等,我們接口調(diào)用把Hystrix的一些信息收集到RabbitMQ中,然后Turbine從RabbitMQ中獲取監(jiān)控的數(shù)據(jù)。

五、Spring Cloud Hystrix配置說(shuō)明

以下的屬性都是spring cloud 1.5.9版本的。

1.Execution相關(guān)的屬性的配置:

  • hystrix.command.default.execution.isolation.strategy 隔離策略,默認(rèn)是Thread, 可選Thread|Semaphore
  • hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令執(zhí)行超時(shí)時(shí)間,默認(rèn)1000ms
  • hystrix.command.default.execution.timeout.enabled 執(zhí)行是否啟用超時(shí),默認(rèn)啟用true
  • hystrix.command.default.execution.isolation.thread.interruptOnTimeout 發(fā)生超時(shí)是是否中斷,默認(rèn)true
  • hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并發(fā)請(qǐng)求數(shù),默認(rèn)10,該參數(shù)當(dāng)使用ExecutionIsolationStrategy.SEMAPHORE策略時(shí)才有效。如果達(dá)到最大并發(fā)請(qǐng)求數(shù),請(qǐng)求會(huì)被拒絕。理論上選擇semaphore size的原則和選擇thread size一致,但選用semaphore時(shí)每次執(zhí)行的單元要比較小且執(zhí)行速度快(ms級(jí)別),否則的話應(yīng)該用thread。

semaphore應(yīng)該占整個(gè)容器(tomcat)的線程池的一小部分。

2.Fallback相關(guān)的屬性

這些參數(shù)可以應(yīng)用于Hystrix的THREAD和SEMAPHORE策略

  • hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果并發(fā)數(shù)達(dá)到該設(shè)置值,請(qǐng)求會(huì)被拒絕和拋出異常并且fallback不會(huì)被調(diào)用。默認(rèn)10
  • hystrix.command.default.fallback.enabled 當(dāng)執(zhí)行失敗或者請(qǐng)求被拒絕,是否會(huì)嘗試調(diào)用hystrixCommand.getFallback() 。默認(rèn)true

3.Circuit Breaker相關(guān)的屬性

  • hystrix.command.default.circuitBreaker.enabled 用來(lái)跟蹤circuit的健康性,如果未達(dá)標(biāo)則讓request短路。默認(rèn)true。
  • hystrix.command.default.circuitBreaker.requestVolumeThreshold 一個(gè)rolling window內(nèi)最小的請(qǐng)求數(shù)。如果設(shè)為20,那么當(dāng)一個(gè)rolling window的時(shí)間內(nèi)(比如說(shuō)1個(gè)rolling window是10秒)收到19個(gè)請(qǐng)求,即使19個(gè)請(qǐng)求都失敗,也不會(huì)觸發(fā)circuit break。默認(rèn)20。這個(gè)參數(shù)非常重要,熔斷器是否打開首先要滿足這個(gè)條件。
  • hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 觸發(fā)短路的時(shí)間值,當(dāng)該值設(shè)為5000時(shí),則當(dāng)觸發(fā)circuit break后的5000毫秒內(nèi)都會(huì)拒絕request,也就是5000毫秒后才會(huì)關(guān)閉circuit。默認(rèn)5000
  • hystrix.command.default.circuitBreaker.errorThresholdPercentage錯(cuò)誤比率閥值,如果錯(cuò)誤率>=該值,circuit會(huì)被打開,并短路所有請(qǐng)求觸發(fā)fallback。默認(rèn)50
  • hystrix.command.default.circuitBreaker.forceOpen 強(qiáng)制打開熔斷器,如果打開這個(gè)開關(guān),那么拒絕所有request,默認(rèn)false
  • hystrix.command.default.circuitBreaker.forceClosed 強(qiáng)制關(guān)閉熔斷器 如果這個(gè)開關(guān)打開,circuit將一直關(guān)閉且忽略circuitBreaker.errorThresholdPercentage

4.Metrics相關(guān)參數(shù)

  • hystrix.command.default.metrics.rollingStats.timeInMilliseconds 設(shè)置統(tǒng)計(jì)的時(shí)間窗口值的,毫秒值,circuit break 的打開會(huì)根據(jù)1個(gè)rolling window的統(tǒng)計(jì)來(lái)計(jì)算。若rolling window被設(shè)為10000毫秒,則rolling window會(huì)被分成n個(gè)buckets,每個(gè)bucket包含success,failure,timeout,rejection的次數(shù)的統(tǒng)計(jì)信息。默認(rèn)10000
  • hystrix.command.default.metrics.rollingStats.numBuckets 設(shè)置一個(gè)rolling window被劃分的數(shù)量,若numBuckets=10,rolling window=10000,那么一個(gè)bucket的時(shí)間即1秒。必須符合rolling window % numberBuckets == 0。默認(rèn)10
  • hystrix.command.default.metrics.rollingPercentile.enabled 執(zhí)行時(shí)是否enable指標(biāo)的計(jì)算和跟蹤,默認(rèn)true
  • hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 設(shè)置rolling percentile window的時(shí)間,默認(rèn)60000
  • hystrix.command.default.metrics.rollingPercentile.numBuckets 設(shè)置rolling percentile window的numberBuckets。邏輯同上。默認(rèn)6
  • hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window=10s,若這10s里有500次執(zhí)行,只有最后100次執(zhí)行會(huì)被統(tǒng)計(jì)到bucket里去。增加該值會(huì)增加內(nèi)存開銷以及排序的開銷。默認(rèn)100
  • hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 記錄health 快照(用來(lái)統(tǒng)計(jì)成功和錯(cuò)誤綠)的間隔,默認(rèn)500ms

5.Request Context 相關(guān)參數(shù)

hystrix.command.default.requestCache.enabled 默認(rèn)true,需要重載getCacheKey(),返回null時(shí)不緩存
hystrix.command.default.requestLog.enabled 記錄日志到HystrixRequestLog,默認(rèn)true

6.Collapser Properties 相關(guān)參數(shù)

hystrix.collapser.default.maxRequestsInBatch 單次批處理的最大請(qǐng)求數(shù),達(dá)到該數(shù)量觸發(fā)批處理,默認(rèn)Integer.MAX_VALUE
hystrix.collapser.default.timerDelayInMilliseconds 觸發(fā)批處理的延遲,也可以為創(chuàng)建批處理的時(shí)間+該值,默認(rèn)10
hystrix.collapser.default.requestCache.enabled 是否對(duì)HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默認(rèn)true

7.ThreadPool 相關(guān)參數(shù)

線程數(shù)默認(rèn)值10適用于大部分情況(有時(shí)可以設(shè)置得更?。?,如果需要設(shè)置得更大,那有個(gè)基本得公式可以follow:
requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room
每秒最大支撐的請(qǐng)求數(shù) (99%平均響應(yīng)時(shí)間 + 緩存值)
比如:每秒能處理1000個(gè)請(qǐng)求,99%的請(qǐng)求響應(yīng)時(shí)間是60ms,那么公式是:
1000 (0.060+0.012)

基本得原則時(shí)保持線程池盡可能小,他主要是為了釋放壓力,防止資源被阻塞。
當(dāng)一切都是正常的時(shí)候,線程池一般僅會(huì)有1到2個(gè)線程激活來(lái)提供服務(wù)

  • hystrix.threadpool.default.coreSize 并發(fā)執(zhí)行的最大線程數(shù),默認(rèn)10
  • hystrix.threadpool.default.maxQueueSize BlockingQueue的最大隊(duì)列數(shù),當(dāng)設(shè)為-1,會(huì)使用SynchronousQueue,值為正時(shí)使用LinkedBlcokingQueue。該設(shè)置只會(huì)在初始化時(shí)有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默認(rèn)-1。
  • hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize沒有達(dá)到,達(dá)到queueSizeRejectionThreshold該值后,請(qǐng)求也會(huì)被拒絕。因?yàn)閙axQueueSize不能被動(dòng)態(tài)修改,這個(gè)參數(shù)將允許我們動(dòng)態(tài)設(shè)置該值。if maxQueueSize == -1,該字段將不起作用
  • hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize設(shè)成一樣(默認(rèn)實(shí)現(xiàn))該設(shè)置無(wú)效。如果通過(guò)plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定義實(shí)現(xiàn),該設(shè)置才有用,默認(rèn)1.
  • hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 線程池統(tǒng)計(jì)指標(biāo)的時(shí)間,默認(rèn)10000
  • hystrix.threadpool.default.metrics.rollingStats.numBuckets 將rolling window劃分為n個(gè)buckets,默認(rèn)10

六、Spring Cloud Hystrix線程調(diào)整和計(jì)算

在實(shí)際使用過(guò)程中會(huì)涉及多個(gè)微服務(wù),可能有些微服務(wù)使用的線程池過(guò)大,有些服務(wù)使用的線程池小,有些服務(wù)的超時(shí)時(shí)間長(zhǎng),有的短,所以Hystrix官方也提供了一些方法供我們來(lái)計(jì)算和調(diào)整這些配置,總的宗旨是,通過(guò)自我預(yù)判的配置先發(fā)布到生產(chǎn)或測(cè)試,然后查看它具體的運(yùn)行情況,在調(diào)整為更符合業(yè)務(wù)的配置,通常做法有:

1.超過(guò)時(shí)間默認(rèn)為1000ms,如果業(yè)務(wù)明顯超過(guò)1000ms,則根據(jù)自己的業(yè)務(wù)進(jìn)行修改。

2.線程池默認(rèn)10,如果知道確實(shí)要使用更多時(shí)可以調(diào)整。

3.金絲雀發(fā)布,如果成功則保持。

4.在生產(chǎn)環(huán)境中運(yùn)行超過(guò)24小時(shí)。

5.如果系統(tǒng)有告警和監(jiān)控,那么可以依靠他們捕捉問(wèn)題。

6.運(yùn)行24小時(shí)后,通過(guò)延時(shí)百分位和流量來(lái)計(jì)算有意義的最低滿足值。

7.在生產(chǎn)或測(cè)試環(huán)境中實(shí)時(shí)修改值,然后用儀表盤監(jiān)控。

8.如果斷路器產(chǎn)生變化和影響,則需要再次確認(rèn)這個(gè)配置。                             

官方例子如圖,Threadpool的大小為10,如下計(jì)算公式:

每秒請(qǐng)求的峰值 X 99%的延遲百分比(請(qǐng)求響應(yīng)的時(shí)間)+ 預(yù)留緩存的值

即 30 x 0.2s  = 6 + 預(yù)留緩存的值 = 10 ,這里預(yù)留了4個(gè)線程數(shù)。

Thread Timeout:預(yù)留了一個(gè)足夠的時(shí)間,250ms,然后加上重試一次的中位數(shù)值。

Connect Timeout & Read Timeout:100ms和250ms,這兩個(gè)值的設(shè)置方法遠(yuǎn)高于中位數(shù)值,以適應(yīng)大多數(shù)請(qǐng)求。

在實(shí)際的生產(chǎn)測(cè)試過(guò)程中,配置每個(gè)服務(wù)時(shí)可以根據(jù)官方推薦的這些方法來(lái)測(cè)試自己的業(yè)務(wù)需要的數(shù)值,這樣產(chǎn)生最合適的配置。

七、Spring Cloud Hystrix源碼分析

Spring Cloud Hystrix的使用: 

  • 1.啟動(dòng)類添加@EnableHystrix注解。 
  • 2.方法上添加@HystrixCommand注解,并指定fallback的方法。

查看@EnableHystrix注解

/**
 * Convenience annotation for clients to enable Hystrix circuit breakers (specifically).
 * Use this (optionally) in case you want discovery and know for sure that it is Hystrix
 * you want. All it does is turn on circuit breakers and let the autoconfiguration find
 * the Hystrix classes if they are available (i.e. you need Hystrix on the classpath as
 * well).
 *
 * @author Dave Syer
 * @author Spencer Gibb
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableCircuitBreaker
public @interface EnableHystrix {
}

這個(gè)注解的功能就是開啟Hystrix。這個(gè)注解還引入了@EnableCircuitBreaker注解。

在代碼同一級(jí)目錄下,還可以看到兩個(gè)配置類:HystrixAutoConfiguration和HystrixCircuitBreakerConfiguration。 
下面是HystrixAutoConfiguration配置類的配置:

@Configuration
@ConditionalOnClass({ Hystrix.class, HealthIndicator.class })
@AutoConfigureAfter({ HealthIndicatorAutoConfiguration.class })
public class HystrixAutoConfiguration {
    @Bean
    @ConditionalOnEnabledHealthIndicator("hystrix")
    public HystrixHealthIndicator hystrixHealthIndicator() {
        return new HystrixHealthIndicator();
    }
}

從代碼中可以看到,HystrixAutoConfiguration這個(gè)配置類主要是hystrix的健康檢查的配置。再看下HystrixCircuitBreakerConfiguration這個(gè)類,這個(gè)類里面就配置了很多內(nèi)容。

@Bean
public HystrixCommandAspect hystrixCommandAspect() {
    return new HystrixCommandAspect();
}

這里返回了HystrixCommandAspect的bean,這個(gè)切面中定義了Pointcut:

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {
}
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
public void hystrixCollapserAnnotationPointcut() {
}

所以,這個(gè)Aspect就是利用AOP切面對(duì) HystrixCommand 、 HystrixCollapser 兩種注解的方法進(jìn)行擴(kuò)展處理。 
我們?cè)诜椒ㄉ咸砑覢HystrixCommand注解,就會(huì)經(jīng)過(guò)這個(gè)切面,這個(gè)切面中定義了@Around(…)攔截所有請(qǐng)求。

下面看下這個(gè)方法:

@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
    Method method = getMethodFromTarget(joinPoint);
    Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
    if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
        throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
                "annotations at the same time");
    }
    MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
    MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
    HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
    ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
            metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
    Object result;
    try {
        result = CommandExecutor.execute(invokable, executionType, metaHolder);
    } catch (HystrixBadRequestException e) {
        throw e.getCause();
    }
    return result;
}

這個(gè)方法中,一開始先獲取攔截的Method,然后判斷,如果方法上同時(shí)加了@HystrixCommand和@HystrixCollapser兩個(gè)注解的話,就拋異常。 
在創(chuàng)建MetaHolder的時(shí)候,調(diào)用了MetaHolderFactory的create方法,MetaHolderFactory有兩個(gè)子類,CollapserMetaHolderFactory和CommandMetaHolderFactory,最終執(zhí)行的是子類的create方法,下面是CommandMetaHolderFactory中的create方法:

private static class CommandMetaHolderFactory extends MetaHolderFactory {
    @Override
    public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
        HystrixCommand hystrixCommand = method.getAnnotation(HystrixCommand.class);
        ExecutionType executionType = ExecutionType.getExecutionType(method.getReturnType());
        MetaHolder.Builder builder = metaHolderBuilder(proxy, method, obj, args, joinPoint);
        return builder.defaultCommandKey(method.getName())
                        .hystrixCommand(hystrixCommand)
                        .observableExecutionMode(hystrixCommand.observableExecutionMode())
                        .executionType(executionType)
                        .observable(ExecutionType.OBSERVABLE == executionType)
                        .build();
    }
}
MetaHolder.Builder metaHolderBuilder(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
    MetaHolder.Builder builder = MetaHolder.builder()
            .args(args).method(method).obj(obj).proxyObj(proxy)
            .defaultGroupKey(obj.getClass().getSimpleName())
            .joinPoint(joinPoint);
    if (isCompileWeaving()) {
        builder.ajcMethod(getAjcMethodFromTarget(joinPoint));
    }
    FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(obj.getClass(), method);
    if (fallbackMethod.isPresent()) {
        fallbackMethod.validateReturnType(method);
        builder
                .fallbackMethod(fallbackMethod.getMethod())
                .fallbackExecutionType(ExecutionType.getExecutionType(fallbackMethod.getMethod().getReturnType()));
    }
    return builder;
}

在創(chuàng)建MetaHolder的過(guò)程中,就會(huì)指定fallback方法。 
創(chuàng)建完MetaHolder之后,就會(huì)根據(jù)MetaHolder創(chuàng)建HystrixInvokable。

public HystrixInvokable create(MetaHolder metaHolder) {
    HystrixInvokable executable;
    if (metaHolder.isCollapserAnnotationPresent()) {
        executable = new CommandCollapser(metaHolder);
    } else if (metaHolder.isObservable()) {
        executable = new GenericObservableCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
    } else {
        executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
    }
    return executable;
}

這段代碼里定義了后續(xù)真正執(zhí)行HystrixCommand的GenericCommand實(shí)例

方法最終會(huì)去執(zhí)行CommandExecutor.execute方法:

public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
    Validate.notNull(invokable);
    Validate.notNull(metaHolder);
    switch (executionType) {
        case SYNCHRONOUS: {
            return castToExecutable(invokable, executionType).execute();
        }
        case ASYNCHRONOUS: {
            HystrixExecutable executable = castToExecutable(invokable, executionType);
            if (metaHolder.hasFallbackMethodCommand()
                    && ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {
                return new FutureDecorator(executable.queue());
            }
            return executable.queue();
        }
        case OBSERVABLE: {
            HystrixObservable observable = castToObservable(invokable);
            return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();
        }
        default:
            throw new RuntimeException("unsupported execution type: " + executionType);
    }
}

這里會(huì)分成同步和異步的場(chǎng)景,進(jìn)入execute方法看下:

/**
 * Used for synchronous execution of command.
 * 
 * @return R
 *         Result of {@link #run()} execution or a fallback from {@link #getFallback()} if the command fails for any reason.
 * @throws HystrixRuntimeException
 *             if a failure occurs and a fallback cannot be retrieved
 * @throws HystrixBadRequestException
 *             if invalid arguments or state were used representing a user failure, not a system failure
 * @throws IllegalStateException
 *             if invoked more than once
 */
public R execute() {
    try {
        return queue().get();
    } catch (Exception e) {
        throw decomposeException(e);
    }
}

這個(gè)方法的注釋中說(shuō)明了返回值,可以返回請(qǐng)求的結(jié)果,當(dāng)失敗的時(shí)候,則會(huì)通過(guò)getFallback()方法來(lái)執(zhí)行一個(gè)回退操作,由于是GenericCommand實(shí)例,那就看下這個(gè)實(shí)例中的getFallback()方法:

@Override
protected Object getFallback() {
    if (getFallbackAction() != null) {
        final CommandAction commandAction = getFallbackAction();
        try {
            return process(new Action() {
                @Override
                Object execute() {
                    MetaHolder metaHolder = commandAction.getMetaHolder();
                    Object[] args = createArgsForFallback(metaHolder, getExecutionException());
                    return commandAction.executeWithArgs(commandAction.getMetaHolder().getFallbackExecutionType(), args);
                }
            });
        } catch (Throwable e) {
            LOGGER.error(FallbackErrorMessageBuilder.create()
                    .append(commandAction, e).build());
            throw new FallbackInvocationException(e.getCause());
        }
    } else {
        return super.getFallback();
    }
}

大體的一個(gè)流程也就知道了,就是通過(guò)HystrixCommandAspect,請(qǐng)求成功返回接口的結(jié)果,請(qǐng)求失敗執(zhí)行fallback的邏輯。

八、總結(jié)

在現(xiàn)代微服務(wù)架構(gòu)中,服務(wù)的高可用性和穩(wěn)定性是系統(tǒng)設(shè)計(jì)的核心要素之一。Spring Cloud Hystrix作為一個(gè)優(yōu)秀的容錯(cuò)框架,通過(guò)熔斷器、線程池隔離和降級(jí)策略,為我們提供了一套有效的解決方案來(lái)應(yīng)對(duì)服務(wù)調(diào)用中的各種異常情況。通過(guò)合理使用Hystrix,我們能夠確保在某個(gè)服務(wù)出現(xiàn)故障時(shí),依賴它的其他服務(wù)不會(huì)受到影響,從而實(shí)現(xiàn)整個(gè)系統(tǒng)的健壯性和彈性。

本文介紹了Hystrix的基本概念、工作原理以及其在實(shí)際開發(fā)中的應(yīng)用方式。通過(guò)對(duì)Hystrix的深入學(xué)習(xí),開發(fā)者可以在分布式系統(tǒng)中實(shí)現(xiàn)精細(xì)的錯(cuò)誤處理機(jī)制,并能夠及時(shí)響應(yīng)系統(tǒng)中的異常,避免服務(wù)的連鎖崩潰。盡管Hystrix在一些場(chǎng)景下已經(jīng)被新的技術(shù)替代(如Resilience4j),但它依然在許多老舊系統(tǒng)中扮演著重要角色,是微服務(wù)容錯(cuò)設(shè)計(jì)的經(jīng)典實(shí)踐之一。

總之,Spring Cloud Hystrix為我們提供了一個(gè)有效的框架來(lái)保障微服務(wù)架構(gòu)中的高可用性和彈性,它的設(shè)計(jì)理念和實(shí)現(xiàn)方式仍然值得我們?cè)诂F(xiàn)代開發(fā)中借鑒和使用。希望通過(guò)本文的講解,讀者能夠深入理解Hystrix的精髓,掌握如何在項(xiàng)目中應(yīng)用它,為構(gòu)建健壯的分布式系統(tǒng)提供有力支持。

到此這篇關(guān)于Spring Cloud Hystrix原理與注意事項(xiàng)的文章就介紹到這了,更多相關(guān)Spring Cloud Hystrix內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java agent使用全解析

    java agent使用全解析

    這篇文章主要介紹了javaagent的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Springboot筆記之熱部署及不生效的解決方案

    Springboot筆記之熱部署及不生效的解決方案

    這篇文章主要介紹了Springboot筆記之熱部署及不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 使用Java制作一個(gè)簡(jiǎn)單的記事本

    使用Java制作一個(gè)簡(jiǎn)單的記事本

    本文給大家?guī)?lái)的是使用Java制作一個(gè)簡(jiǎn)單的記事本的代碼,有相同需要的朋友可以參考下
    2015-02-02
  • Spring IOC相關(guān)注解運(yùn)用(上篇)

    Spring IOC相關(guān)注解運(yùn)用(上篇)

    這篇文章主要介紹了Spring?IOC相關(guān)注解的運(yùn)用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • myeclipse創(chuàng)建servlet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    myeclipse創(chuàng)建servlet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了myeclipse創(chuàng)建servlet的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java實(shí)現(xiàn)線程安全單例模式的五種方式的示例代碼

    Java實(shí)現(xiàn)線程安全單例模式的五種方式的示例代碼

    這篇文章主要介紹了Java中實(shí)現(xiàn)線程安全單例模式的五種方式:餓漢式、枚舉單例、懶漢式、DCL懶漢式和靜態(tài)內(nèi)部類懶漢單例,感興趣的可以了解一下
    2022-03-03
  • Spring基礎(chǔ)篇之初識(shí)DI和AOP

    Spring基礎(chǔ)篇之初識(shí)DI和AOP

    這篇文章主要為大家詳細(xì)介紹了Spring基礎(chǔ)篇之初識(shí)DI和AOP,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java 抽象類和接口的區(qū)別詳細(xì)解析

    java 抽象類和接口的區(qū)別詳細(xì)解析

    abstractclass和interface是Java語(yǔ)言中對(duì)于抽象類定義進(jìn)行支持的兩種機(jī)制,正是由于這兩種機(jī)制的存在,才賦予了Java強(qiáng)大的面向?qū)ο竽芰?需要了解的朋友可以參考下
    2012-11-11
  • java對(duì)象初始化順序驗(yàn)證示例

    java對(duì)象初始化順序驗(yàn)證示例

    以下這段小程序?qū)φ{(diào)用對(duì)象構(gòu)造函數(shù)時(shí),父類構(gòu)造函數(shù)、成員變量初始化函數(shù),以及非靜態(tài)初始化塊調(diào)用順序進(jìn)行驗(yàn)證,不考慮靜態(tài)成員及靜態(tài)初始化塊
    2014-02-02
  • java.net.MalformedURLException異常的解決方法

    java.net.MalformedURLException異常的解決方法

    下面小編就為大家?guī)?lái)一篇java.net.MalformedURLException異常的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05

最新評(píng)論