關(guān)于spring cloud的組件前面已經(jīng)介紹兩個(gè)了, 學(xué)習(xí)的過(guò)程也是循序漸進(jìn)的, 如果前面寫(xiě)的關(guān)于Eureka和Feign兩個(gè)組件還沒(méi)有看的同學(xué),可以點(diǎn)擊以下鏈接進(jìn)行學(xué)習(xí);
spring cloud之Eureka--服務(wù)治理
spring cloud使用過(guò)Eureka怎么進(jìn)行服務(wù)間相互訪(fǎng)問(wèn)--Feign
下面是我自己在github上的spring cloud的demo
spring_cloud_demo
下面進(jìn)入正題;
1.Hystrix
Hystrix對(duì)應(yīng)的中文名字是“豪豬”蹂随,豪豬周身長(zhǎng)滿(mǎn)了刺润脸,能保護(hù)自己不受天敵的傷害羊苟,代表了一種防御機(jī)制,這與Hystrix本身的功能不謀而合澡谭,因此Netflix團(tuán)隊(duì)將該框架命名為Hystrix定鸟,并使用了對(duì)應(yīng)的卡通形象做作為logo
1.1什么是Hystrix
在一個(gè)分布式系統(tǒng)里孽拷,許多依賴(lài)不可避免的會(huì)調(diào)用失敗荠藤,比如超時(shí)、異常等书妻,如何能夠保證在一個(gè)依賴(lài)出問(wèn)題的情況下船响,不會(huì)導(dǎo)致整體服務(wù)失敗,這個(gè)就是Hystrix需要做的事情躲履。Hystrix提供了熔斷见间、隔離、Fallback崇呵、cache缤剧、監(jiān)控等功能,能夠在一個(gè)域慷、或多個(gè)依賴(lài)同時(shí)出現(xiàn)問(wèn)題時(shí)保證系統(tǒng)依然可用荒辕。
1.2為什么使用Hystrix
在微服務(wù)架構(gòu)中汗销,根據(jù)業(yè)務(wù)來(lái)拆分成一個(gè)個(gè)的服務(wù),服務(wù)與服務(wù)之間可以相互調(diào)用(RPC) 抵窒。為了保證其高可用弛针,單個(gè)服務(wù)通常會(huì)集群部署。由于網(wǎng)絡(luò)原因或者自身的原因李皇,服務(wù)并不能保證100%可用削茁,如果單個(gè)服務(wù)出現(xiàn)問(wèn)題,調(diào)用這個(gè)服務(wù)就會(huì)出現(xiàn)線(xiàn)程阻塞掉房,此時(shí)若有大量的請(qǐng)求涌入茧跋,Servlet容器的線(xiàn)程資源會(huì)被消耗完畢,導(dǎo)致服務(wù)癱瘓卓囚。服務(wù)與服務(wù)之間的依賴(lài)性瘾杭,故障會(huì)傳播,會(huì)對(duì)整個(gè)微服務(wù)系統(tǒng)造成災(zāi)難性的嚴(yán)重后果哪亿,這就是服務(wù)故障的“雪崩”效應(yīng)粥烁。
如下圖所示:A作為服務(wù)提供者,B為A的服務(wù)消費(fèi)者蝇棉,C和D是B的服務(wù)消費(fèi)者讨阻。A不可用引起了B的不可用,并將不可用像滾雪球一樣放大到C和D時(shí)篡殷,雪崩效應(yīng)就形成了钝吮。
1.3Hystrix是如何實(shí)現(xiàn)
(1)通過(guò)HystrixCommand或者HystrixObservableCommand來(lái)封裝對(duì)外部依賴(lài)的訪(fǎng)問(wèn)請(qǐng)求,這個(gè)訪(fǎng)問(wèn)請(qǐng)求一般會(huì)運(yùn)行在獨(dú)立的線(xiàn)程中板辽,資源隔離
(2)對(duì)于超出我們?cè)O(shè)定閾值的服務(wù)調(diào)用纠屋,直接進(jìn)行超時(shí)瞪讼,不允許其耗費(fèi)過(guò)長(zhǎng)時(shí)間阻塞住。這個(gè)超時(shí)時(shí)間默認(rèn)是99.5%的訪(fǎng)問(wèn)時(shí)間吸占,但是一般我們可以自己設(shè)置一下
(3)為每一個(gè)依賴(lài)服務(wù)維護(hù)一個(gè)獨(dú)立的線(xiàn)程池巧鸭,或者是semaphore瓶您,當(dāng)線(xiàn)程池已滿(mǎn)時(shí),直接拒絕對(duì)這個(gè)服務(wù)的調(diào)用
(4)對(duì)依賴(lài)服務(wù)的調(diào)用的成功次數(shù)纲仍,失敗次數(shù)呀袱,拒絕次數(shù),超時(shí)次數(shù)郑叠,進(jìn)行統(tǒng)計(jì)
(5)如果對(duì)一個(gè)依賴(lài)服務(wù)的調(diào)用失敗次數(shù)超過(guò)了一定的閾值夜赵,自動(dòng)進(jìn)行熔斷,在一定時(shí)間內(nèi)對(duì)該服務(wù)的調(diào)用直接降級(jí)乡革,一段時(shí)間后再自動(dòng)嘗試恢復(fù)
(6)當(dāng)一個(gè)服務(wù)調(diào)用出現(xiàn)失敗寇僧,被拒絕摊腋,超時(shí),短路等異常情況時(shí)嘁傀,自動(dòng)調(diào)用fallback降級(jí)機(jī)制
(7)對(duì)屬性和配置的修改提供近實(shí)時(shí)的支持
2.項(xiàng)目中使用Hystrix
2.1添加依賴(lài)
<!--添加熔斷器依賴(lài)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
該依賴(lài)加在我的demo中的父項(xiàng)目中
2.2添加注解
在spring boot的啟動(dòng)類(lèi)上添加注解@EnableHystrix
package cn.cooplan.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableHystrix //開(kāi)啟熔斷器
@EnableFeignClients
@EnableEurekaClient //開(kāi)啟Eureka客戶(hù)端服務(wù)
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
//Feigx依賴(lài)的請(qǐng)求對(duì)象
@Bean
RestTemplate restTemplate (){
return new RestTemplate();
}
}
2.3測(cè)試+解釋
需要在你請(qǐng)求的方法上添加 @HystrixCommand("發(fā)生異常時(shí)訪(fǎng)問(wèn)的方法名") 在同一個(gè)類(lèi)中編寫(xiě)異常時(shí)進(jìn)行的方法處理, 具體實(shí)現(xiàn)如下:
package cn.cooplan.order.service.impl;
import cn.cooplan.order.feign.GoodsFeignClient;
import cn.cooplan.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import dao.OrderDao;
import dao.OrderGoodsDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import pojo.Goods;
import pojo.Order;
import pojo.OrderGoods;
import java.util.ArrayList;
import java.util.List;
/**
* @Author MaoLG
* @Date 2018/12/7 14:03
*/
@Service
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private OrderGoodsDao orderGoodsDao;
@Autowired
private GoodsFeignClient goodsFeignClient;
/*在你請(qǐng)求的方法上添加@HystrixCommand注解, 參數(shù)指定發(fā)生錯(cuò)誤時(shí)調(diào)取的方法
該方法要保持參數(shù)列表相同, 返回值相同, 拋出異常相同, 非靜態(tài)方法;
總結(jié)的說(shuō)就是除了方法名不一樣,其他都一樣;
*/
@HystrixCommand(fallbackMethod = "getOrderInGoodsHystrix")
@Override
public List<Goods> getOrderInGoods(Integer orderId) {
OrderGoods o = new OrderGoods();
o.setOrderId(orderId);
QueryWrapper queryWrapper = new QueryWrapper(o);
List<OrderGoods> ogs = orderGoodsDao.selectList(queryWrapper);
List<Goods> goodses = new ArrayList<>();
for (OrderGoods og: ogs) {
Goods goods = goodsFeignClient.getGoodsById(og.getGoodsId());
goodses.add(goods);
}
return goodses;
}
//請(qǐng)求的方法發(fā)生錯(cuò)誤/請(qǐng)求超時(shí)調(diào)取該方法
public List<Goods> getOrderInGoodsHystrix(Integer orderId){
List<Goods> goodses = new ArrayList<>();
Goods goods = new Goods();
goods.setName("商品錯(cuò)誤");
goodses.add(goods);
return goodses;
}
}
Hystrix成功后:
無(wú)異常情況
異常情況
進(jìn)入的方法:
異常效果
詳細(xì)請(qǐng)見(jiàn)github上的spring cloud的demo
spring_cloud_demo
歡迎大家在下面留言討論;