[SpringCloud學習筆記4]Hystrix入門及使用
標簽: JAVA SpringCloud 學習筆記 分布式 java spring 中間件
Hystrix入門及使用
一、Hystrix簡介及功能
SpringCloud已經大大降低了我們各個服務之間的耦合性,但每個服務之間的調用卻緊密聯系,不可切斷,隨著分布式服務的數量增多,如果出現意外導致其中一個無法正常工作,會導致整個服務都停止,這顯然是不合理的.
Hystrix的出現能夠在某個依賴出問題的情況下,不導致整個服務失敗.也就是說相當于一個斷路器,通過監控斷路,返回一個符合預期,可處理的備選響應,而不是直接返回異常中斷或者長時間等待,增加分布式系統的彈性.
目前Hystrix已經停更,但其設計思想值得學習
二、Hystrix重要概念
1.服務降級(fallback)
服務器忙,直接向客戶端拋出提示,請稍后再試,也就是一個兜底的處理方案
服務降級的情況:
- 程序運行異常
- 超時
- 服務熔斷
- 線程池/信號量打滿
2.服務熔斷(break)
服務器運載達到上限,拒絕客戶端訪問,然后進行服務降級,然后主見恢復服務
3.服務限流(flowlimit)
如果有高并發操作,對流量進行限制,進行排隊處理,防止服務器運載上限
三、Hystrix實現
1.構建子模塊
1.改pom
<dependencies>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--監控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--熱部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.編寫yml
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
#表示向注冊中心注冊自己
register-with-eureka: true
#表明要從注冊中心中抓取自己的信息,集群必須要設置成true才能配合ribbon
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
3.主方法啟動
@SpringBootApplication
@EnableHystrix
@EnableEurekaClient
public class PaymentHystrixMain8001 {
public static void main(String[] args){
SpringApplication.run(PaymentHystrixMain8001.class,args);
}
}
4.service層編寫
@Service
public class PaymentHystrixService {
public String pamentInfo_OK(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_OK,id=" + id + "\t" + "成功咯~~~~";
}
public String pamentInfo_TimeOut(Integer id) {
int sleepTime = 3;
try {
TimeUnit.SECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "小睡一會"+sleepTime+"秒成功咯~~~~";
}
}
5.controller層編寫
@RestController
@Slf4j
public class PaymentHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@GetMapping("/payment/hystrix/ok/{id}")
public String pamentInfo_OK(@PathVariable Integer id) {
return paymentHystrixService.pamentInfo_OK(id);
}
@GetMapping("/payment/hystrix/timeout/{id}")
public String pamentInfo_TimeOut(@PathVariable Integer id) {
return paymentHystrixService.pamentInfo_TimeOut(id);
}
}
2.線程高壓測試
設置20000個線程形成高并發場景
本來不會卡頓的快速請求也變卡了.
也就是服務器中的所有線程被使用完了,導致只能等待.
1.加入消費者端
1.改pom
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--監控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引用自己定義的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.xiaoxiao.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<!--熱部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.yml文件
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:7001/eureka/
3.主啟動類
@SpringBootApplication
@EnableHystrix
@EnableEurekaClient
public class HystrixOrderMain80 {
public static void main(String[] args){
SpringApplication.run(HystrixOrderMain80.class,args);
}
}
4.編寫feign接口
@Component
@FeignClient(name = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface OrderHystrixService {
@GetMapping("/payment/hystrix/ok/{id}")
public String pamentInfo_OK(@PathVariable Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String pamentInfo_TimeOut(@PathVariable Integer id) ;
}
5.編寫controller
@RestController
@Slf4j
public class OrderHystrixController {
@Resource
private OrderHystrixService orderHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String pamentInfo_OK(@PathVariable Integer id){
return "我是消費者80"+orderHystrixService.pamentInfo_OK(id);
}
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String pamentInfo_TimeOut(@PathVariable Integer id) {
return "我是消費者80"+orderHystrixService.pamentInfo_TimeOut(id);
}
}
2.加入線程組
顯然,加入后80請求訪問也會非常卡
3.Hystrix應用
- 如果訪問對方服務器超時,調用者不能一直等待,需要服務降級
- 如果訪問服務器down機,調用者不能一直等待,需要進行服務降級
- 如果對方服務器OK,但是調用者自己出了故障,報錯或者是對時間反饋有要求但對方未達到,也需要進行服務降級
4.支付端服務降級
1.制定一個fallback備選方法
public String pamentInfo_TimeOutHandler(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "我失敗了,請你返回一下謝謝";
}
2.設置降級配置
@Service
public class PaymentHystrixService {
public String pamentInfo_OK(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_OK,id=" + id + "\t" + "成功咯~~~~";
}
@HystrixCommand(fallbackMethod = "pamentInfo_TimeOutHandler", commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
})
public String pamentInfo_TimeOut(Integer id){
int sleepTime = 5;
try{
TimeUnit.SECONDS.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
return"線程池:"+Thread.currentThread().
getName() +"pamentInfo_TimeOut,id="+id +"\t"+"小睡一會"+sleepTime+"秒成功咯~~~~";
}
public String pamentInfo_TimeOutHandler(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "我失敗了,請你返回一下謝謝";
}
}
如果3秒沒有響應就服務降級,這里休眠5秒,所以降級了
同理,如果出現異常,也會進行服務降級處理,自動調動備選方法
5.消費端服務降級
1.改yml
feign:
hystrix:
enabled: true
開啟Hystrix支持
2.主方法加入@EnableHystrix
3.修改controller
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "OrderTimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
public String pamentInfo_TimeOut(@PathVariable("id") Integer id) {
return "我是消費者80"+orderHystrixService.pamentInfo_TimeOut(id);
}
public String OrderTimeOutHandler(@PathVariable("id") Integer id) {
return "我是消費者80:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "我是消費端的降級!!!!";
}
6.設置默認fallback方法
需要服務降級要加@HystrixCommand注解,如果沒加fallback屬性,就找默認fallback,如果加了,就找指定的
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "GlobalFallback")
public class OrderHystrixController {
@Resource
private OrderHystrixService orderHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
@HystrixCommand
public String pamentInfo_OK(@PathVariable("id") Integer id) {
return "我是消費者80" + orderHystrixService.pamentInfo_OK(id);
}
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
/* @HystrixCommand(fallbackMethod = "OrderTimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000")
})*/
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000")
})
public String pamentInfo_TimeOut(@PathVariable("id") Integer id) {
return "我是消費者80" + orderHystrixService.pamentInfo_TimeOut(id);
}
public String OrderTimeOutHandler(@PathVariable("id") Integer id) {
return "我是消費者80:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "我是消費端的降級!!!!";
}
//全局fallback
public String GlobalFallback() {
return "我是消費者80:" + Thread.currentThread().getName() + "GlobalFallback,id=" + "\t" + "我是一個全局降級方法!!!!";
}
}
7.實現feign接口類實現解耦
對于feign接口的每個方法,都需要一個fallback耦合度太高,而且如果對面服務器down機,會導致超時或不友善連接,這時候需要進行服務降級.具體方法就是使用一個類去實現feign接口然后標注為fallback類
@Component
@FeignClient(name = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = OrderFeignFallbackService.class)
public interface OrderHystrixService {
@GetMapping("/payment/hystrix/ok/{id}")
public String pamentInfo_OK(@PathVariable("id") Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String pamentInfo_TimeOut(@PathVariable("id") Integer id) ;
}
@Component
public class OrderFeignFallbackService implements OrderHystrixService {
@Override
public String pamentInfo_OK(Integer id) {
return "... OrderFeignFallbackService pamentInfo_OK,(┬_┬)";
}
@Override
public String pamentInfo_TimeOut(Integer id) {
return "... OrderFeignFallbackService pamentInfo_TimeOut (┬_┬)";
}
}
8.服務熔斷
當訪問服務器已經服務降級,并且還是繼續滿足服務降級的情況下,在一定失敗率的前提下回開啟服務熔斷,類似于電路圖中的開路,將本來閉合的電路變成開路,他也有一定的自我修復功能,就是保持一個"半開半閉的狀態",會在一定時間后放幾個信息過去,如果通過,又能回復到閉合.熔斷過程中是直接調用服務降級的fallback方法.
總而言之就是服務降級→到一定數量后服務熔斷→放出消息可用后關閉熔斷,恢復正常
1.服務層
@Service
public class PaymentHystrixService {
public String pamentInfo_OK(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_OK,id=" + id + "\t" + "成功咯~~~~";
}
@HystrixCommand(fallbackMethod = "pamentInfo_TimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
})
public String pamentInfo_TimeOut(Integer id) {
// int a = 10 / 0;
int sleepTime = 1000;
try {
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "線程池:" + Thread.currentThread().
getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "小睡一會" + sleepTime + "秒成功咯~~~~";
}
public String pamentInfo_TimeOutHandler(Integer id) {
return "線程池:" + Thread.currentThread().getName() + "pamentInfo_TimeOut,id=" + id + "\t" + "我失敗了,請你返回一下謝謝";
}
//=====服務熔斷
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否開啟斷路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 請求次數
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 時間窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失敗率達到多少后跳閘
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
if(id < 0)
{
throw new RuntimeException("******id 不能負數");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"調用成功,流水號: " + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
{
return "id 不能負數,請稍后再試,/(ㄒoㄒ)/~~ id: " +id;
}
}
2.controller層
//服務熔斷
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
String result = paymentHystrixService.paymentCircuitBreaker(id);
log.info("*****result:"+result);
return result;
}
3.主方法加入注解
@SpringBootApplication
@EnableHystrix
@EnableEurekaClient
public class PaymentHystrixMain8001 {
public static void main(String[] args){
SpringApplication.run(PaymentHystrixMain8001.class,args);
}
}
//@EnableHystrix注解含有@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableCircuitBreaker
public @interface EnableHystrix {
}
9.Hystrix圖形化儀表盤搭建
1.新建模塊cloud-consumer-feign-hystrix-order80
2.修改pom文件
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3.編寫yml文件
server:
port: 9001
4.編寫主方法
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {
public static void main(String[] args){
SpringApplication.run(HystrixDashboardMain9001.class,args);
}
}
5.訪問地址
http://localhost:9001/hystrix
6.在被監控的模塊主方法下添加配置
老師說是舊版本的坑,否則會出現Unable to connect to Command Metric Stream的錯誤
/**
*此配置是為了服務監控而配置,與服務容錯本身無關,springcloud升級后的坑
*ServletRegistrationBean因為springboot的默認路徑不是"/hystrix.stream",
*只要在自己的項目里配置上下面的servlet就可以了
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
7.輸入被監控的網址
這里根據類來看是http://localhost:8001//hystrix.stream
四、總結
1.學習總結
Hystrix是一個能夠處理服務降級和服務熔斷的優秀框架,核心內容就是服務降級和服務熔斷,還有一個圖形化監控界面儀表盤。
一般是在服務響應超時,服務出現異常,或者是服務器滿負荷,或是服務器down機的情況下需要進行服務降級。服務熔斷是在一定百分比次數失敗訪問服務器出現服務降級進而會出現的功能,熔斷期間無法接受任何信息直接fallback,一段時間后會放幾個信息,如果成功則彈性恢復服務器。
2.注意事項
在HystrixCommandProperties記載了Hystrix的命令屬性
對于@HystrixCommand內屬性的修改,需要重啟微服務,不然有時候會有BUG,熱部署不會更新配置
3.疑惑
為什么在使用消費端調用服務端時設置value并不管用,設置了十秒也好,到了一秒如果服務端沒響應,直接返回timeout的fallback方法。那在hystrixcommand中設置的timevalue不是沒有意義了嗎?
智能推薦
SpringCloud——(4)hystrix
hystrix熔斷降級 文章目錄 hystrix熔斷降級 【一】前言 【二】hystrix介紹 【三】快速構建 【四】鏈接 【一】前言 為什么需要熔斷降級 它是系統負載過高,突發流量或者網絡等各種異常情況介紹,常用的解決方案。在一個分布式系統里,一個服務依賴多個服務,可能存在某個服務調用失敗,比如超時、異常等,如何能夠保證在一個依賴出問題的情下,不會導致整體服務失敗。 什么是熔斷 一般是某個服務故...
[SpringCloud Alibaba學習筆記]Sentinel的入門,配置及使用(結合openfeign,nacos)
SpringCloud Alibaba Sentinel的入門及使用 一、Sentinel簡介 sentinel源碼 隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。 相較于Hystrix來說,Sentinel是不需要手工搭建,是獨立的,可以有界面化的細粒度統一配置。 二、運行Sentinel ...
SpringCloud入門4---Hystrix(熔斷器組件)
第四篇,我們對SpringCloud中Hystrix(熔斷器組件)做一下簡單的介紹: 1、為什么要使用熔斷器 這里我們要先了解下什么是服務雪崩效應?在微服務架構中通常會有多個服務層調用,基礎服務的故障可能會導致級聯故障,進而造成整個系統不可用的情況,這種現象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導...
SpringCloud學習筆記:三、springcloud熔斷降級組件hystrix詳解
本系列博文為學習資料,是根據老師講義,加上自己理解描述整理而成。如有不當之處希望不吝指正,持續更新改正。 服務雪崩 雪崩是系統中的蝴蝶效應導致其發生的原因多種多樣,有不合理的容量設計,或者是高并發 下某一個方法響應變慢,亦或是某臺機器的資源耗盡。從源頭上我們無法完全杜絕雪崩源頭 的發生,但是雪崩的根本原因來源于服務之間的強依賴,所以我們可以提前評估。當整個微 服務系統中,有一個節點出現異常情況,就...
springcloud學習筆記(六)SpringCloud集成Hystrix(1)
對于Hystrix 官方文檔如是說: 在微服務架構中,通常有多層服務調用。 圖1.微服務圖 較低級別的服務中的服務故障可能導致用戶級聯故障。當對特定服務的呼叫達到一定閾值時(Hystrix中的默認值為5秒內的20次故障),電路打開,不進行通話。在錯誤和開路的情況下,開發人員可以提供后備。 圖2. Hystrix回退防止級聯故障 開放式電路會停止級聯故障,并允許不必要的或失敗的服務時間來愈...
猜你喜歡
SpringCloud學習筆記->Ribbon、OpenFeign、Hystrix、GateWay、SpringCloud config
一、Ribbon 負載均衡服務調用 1.1 概念 SpringCloud Ribbon 是基于Netflix Ribbon實現的一套 客戶端負載均衡的工具 簡單的說,Ribbon是Netflix發布的開源項目,主要功能是提供客戶端負載均衡算法和服務調用,Ribbon客戶端組件提供一系列完善的配置項如 連接超時,超時重試等,簡單來說,就是在配置文件中列出Load Balancer后面的所有機器,Ri...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...