SpringCloud-hystrix實(shí)戰(zhàn)01--服務(wù)熔斷

Hystrix是由Netflix開源的一個(gè)延遲和容錯(cuò)庫,用于隔離訪問遠(yuǎn)程系統(tǒng)、服務(wù)或者第三方庫,防止級聯(lián)失敗,從而提升系統(tǒng)的可用性與容錯(cuò)性。Hystrix主要通過以下幾點(diǎn)實(shí)現(xiàn)延遲和容錯(cuò)。

*跳閘機(jī)制:當(dāng)某服務(wù)的錯(cuò)誤率超過一定閾值時(shí),Hystrix可以自動(dòng)或者手動(dòng)跳閘,停止請求該服務(wù)一段時(shí)間。

*資源隔離:Hystrix為每個(gè)依賴都維護(hù)了一個(gè)小型的線程池(或者信號量)。如果該線程池已滿,發(fā)往該依賴的請求就被立即拒絕,而不是排隊(duì)等候,從而加速失敗判定。

*回退機(jī)制:當(dāng)請求失敗、超時(shí)、被拒絕,或當(dāng)斷路器打開時(shí),執(zhí)行回退邏輯。回退邏輯可由開發(fā)人員自行提供,例如返回一個(gè)缺省值。

*包裹請求:使用HystrixCommand(或HystrixObservableCommand)包裹對依賴的調(diào)用邏輯,每個(gè)命令在獨(dú)立線程中執(zhí)行。這使用到了設(shè)計(jì)模式中的“命令模式”。

*監(jiān)控:Hystrix可以近乎實(shí)時(shí)地監(jiān)控運(yùn)行指標(biāo)和配置的變化,例如成功、失敗、超時(shí)、以及被拒絕的請求等。

Feign默認(rèn)已經(jīng)整合了Hystrix,本節(jié)詳細(xì)探討Feign使用Hystrix的具體細(xì)節(jié)(項(xiàng)目中很少有單獨(dú)使用Hystrix的)

服務(wù)雪崩

多個(gè)微服務(wù)之間調(diào)用的時(shí)候,假設(shè)微服務(wù)A調(diào)用微服務(wù)B何微服務(wù)C,微服務(wù)B何微服務(wù)C又調(diào)用其他的微服務(wù),這就是所謂的“扇出”。如果扇出的鏈路上某個(gè)微服務(wù)的調(diào)用響應(yīng)時(shí)間過長或者不可用,對微服務(wù)A的調(diào)用就會占用越來越多的系統(tǒng)資源,進(jìn)而引起系統(tǒng)崩潰。

對于高流量的應(yīng)用來說,單一的后端依賴可能會導(dǎo)致所有服務(wù)器上的所有資源都在幾秒鐘內(nèi)飽和。比失敗更糟糕的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,備份隊(duì)列,線程和其他系統(tǒng)資源緊張,導(dǎo)致整個(gè)系統(tǒng)發(fā)生更多的級聯(lián)故障。這些都表示需要對故障和延遲進(jìn)行隔離和管理,以便單個(gè)依賴關(guān)系的失敗,不能取消整個(gè)應(yīng)用程序或系統(tǒng)。

Hystrix

Hystrix是一個(gè)用于處理分布式系統(tǒng)的延遲和容錯(cuò)的開源庫,在分布式系統(tǒng)里,許多依賴不可避免的會調(diào)用失敗,比如超時(shí)、異常等,Hystrix能夠保證在一個(gè)依賴出問題的情況下,不會導(dǎo)致整體服務(wù)失敗,避免級聯(lián)故障,以提高分布式系統(tǒng)的彈性。

“斷路器”本身是一種開關(guān)裝置,當(dāng)某個(gè)服務(wù)單元發(fā)生故障之后,通過斷路器的故障監(jiān)控(類似熔斷保險(xiǎn)絲),向調(diào)用方返回一個(gè)符合預(yù)期的、可處理的備選響應(yīng)(FallBack),而不是長時(shí)間的等待或者拋出調(diào)用方無法處理的異常,這樣就保證了服務(wù)調(diào)用方的線程不會被長時(shí)間、不必要的占用,從而避免了公章在分布式系統(tǒng)中的蔓延,乃至雪崩。

功能

1.服務(wù)降級
2.服務(wù)熔斷
3.服務(wù)限流
4.接近實(shí)時(shí)的監(jiān)控
。。。。

服務(wù)熔斷

熔斷機(jī)制是應(yīng)對雪崩效應(yīng)的一種微服務(wù)鏈路保護(hù)機(jī)制。

一般是某個(gè)服務(wù)股找那個(gè)或者異常引起,類似現(xiàn)實(shí)世界中的“保險(xiǎn)絲”,當(dāng)某個(gè)異常條件被觸發(fā),直接熔斷整個(gè)服務(wù),而不是一直等到此服務(wù)超時(shí)。

當(dāng)扇出鏈路的某個(gè)微服務(wù)不可用或者響應(yīng)時(shí)間太長時(shí),會進(jìn)行服務(wù)的降級,進(jìn)而熔斷該節(jié)點(diǎn)微服務(wù)的調(diào)用,快速返回“錯(cuò)誤”的響應(yīng)信息。當(dāng)檢測到該節(jié)點(diǎn)微服務(wù)調(diào)用響應(yīng)正常后恢復(fù)調(diào)用鏈路。在SpringCloud框架里熔斷機(jī)制通過Hystrix實(shí)現(xiàn)。Hystrix會監(jiān)控微服務(wù)間調(diào)用的狀況,當(dāng)失敗的調(diào)用到一定閾值,缺省是5秒內(nèi)20次調(diào)用失敗就會啟動(dòng)熔斷機(jī)制。熔斷機(jī)制的注解是@HystrixCommand

實(shí)戰(zhàn)

pom中的依賴

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>

properties中的修改

#-----服務(wù)端口號修改了----
server.port=18084
spring.application.name=springboot-mybatis-provider-001
# 指定eureka server通信地址,注意/eureka/不能少
eureka.client.service-url.defaultZone=http://eureka10002.com:10002/eureka/,http://eureka10003.com:10003/eureka/,http://eureka10004.com:10004/eureka/
# 是否注冊IP到eureka server,如不指定或設(shè)為false,那就會注冊主機(jī)名到eureka server
eureka.instance.prefer-ip-address=true
#修改服務(wù)名稱-------實(shí)例名稱修改了------
eureka.instance.instance-id=springboot-mybatis-provider-hystrix001-18084
#配置actuator監(jiān)控信息
info.app.name=springboot-mybatis-provider-hystrix001-18084
info.company.name=www.zjhc.com
info.build.artifactId=$project.artifactId$
info.build.version=$project.version$

啟動(dòng)類中的修改

controller中的修改

package com.hc.controller;

import com.hc.model.User;
import com.hc.service.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 */
@Controller
public class UserController {

    private Logger logger = Logger.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @RequestMapping("/getRealUserInfo/{id}")
    @ResponseBody
    @HystrixCommand(fallbackMethod = "getRealUserInfo_Hystrix")
    public User getRealUserInfo(@PathVariable Integer id) {
        User user = new User();
//        try {
            user = userService.getRealUserInfo(id);
            if (user == null) {
                logger.info("-----user信息未獲取到-----");
                throw new RuntimeException("haha,就是故意讓你報(bào)錯(cuò)滴 ^_^ ");
            }
//        }catch (Exception e){
//            e.printStackTrace();
//        }
        return user;
    }

    public User getRealUserInfo_Hystrix(@PathVariable Integer id) {
        User user = new User();
        user.setName("該ID:"+id+" 沒有對應(yīng)的信息,null-@HystrixCommand");
        return user;
    }
}

測試結(jié)果如下(背景條件:數(shù)據(jù)庫中沒有id為200的數(shù)據(jù)):

id=1的時(shí)候是有數(shù)據(jù)的

由于沒有id=200的數(shù)據(jù),我們故意手動(dòng)拋出異常,來測試熔斷
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容