Hystrix斷路器
概述
Hystrix是一個(gè)用于處理分布式系統(tǒng)的延遲和容錯(cuò)的開源庫,在分布式系統(tǒng)中膘茎,許多的依賴不可避免的會(huì)調(diào)用失敗熔掺,比如超時(shí),異常等旭愧,Hystrix能夠保證在一個(gè)依賴出問題的情況下颅筋, 不會(huì)導(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)用方的線程不會(huì)被長時(shí)間,不必要的占用螟深,從而避免了故障在分布式系統(tǒng)中的蔓延谐宙。
服務(wù)熔斷
熔斷機(jī)制是應(yīng)對雪崩效應(yīng)的一種微服務(wù)鏈路保護(hù)機(jī)制,當(dāng)扇出鏈路的某一個(gè)微服務(wù)不可用或者響應(yīng)時(shí)間太長界弧,會(huì)進(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會(huì)監(jiān)控微服務(wù)調(diào)用情況条获,當(dāng)失敗達(dá)到一定閾值忠荞。就會(huì)啟動(dòng)熔斷機(jī)制,熔斷機(jī)制的注解是 @HystrixCommand
Hystrix實(shí)操
參照microservicecloud-provider-dept-8001建立microservicecloud-provider-dept-hystrix-8001項(xiàng)目
pom.xml文件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.luo.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-provider-dept-hystrix-8001</artifactId>
<dependencies>
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<!-- 引入自己定義的api通用包帅掘,可以使用Dept部門Entity -->
<dependency>
<groupId>com.luo.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- actuator監(jiān)控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 將微服務(wù)provider側(cè)注冊進(jìn)eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</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-test</artifactId>
</dependency>
<!-- 修改后立即生效委煤,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
application.yml文件
eureka:
client: #客戶端注冊進(jìn)eureka服務(wù)列表內(nèi)
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-dept8001-hystrix #自定義服務(wù)名稱信息
prefer-ip-address: true #訪問路徑可以顯示IP地址
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑
type-aliases-package: com.luo.springcloud.entities # 所有Entity別名類所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservicecloud-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 當(dāng)前數(shù)據(jù)源操作類型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驅(qū)動(dòng)包
url: jdbc:mysql://localhost:3306/cloudDB01 # 數(shù)據(jù)庫名稱
username: root
password: 1234
dbcp2:
min-idle: 5 # 數(shù)據(jù)庫連接池的最小維持連接數(shù)
initial-size: 5 # 初始化連接數(shù)
max-total: 5 # 最大連接數(shù)
max-wait-millis: 200 # 等待連接獲取的最大超時(shí)時(shí)間
eureka:
client: #客戶端注冊進(jìn)eureka服務(wù)列表內(nèi)
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-dept8001-hystrix #自定義服務(wù)名稱信息
prefer-ip-address: true #訪問路徑可以顯示IP地址
info:
app.name: luokangyuan-microservicecloud
company.name: www.luokangyuan.com
build.artifactId: $project.artifactId$
build.version: $project.version$
修改DeptController
Hystrix的作用就是當(dāng)調(diào)用服務(wù)出現(xiàn)異常時(shí)如何解決,模擬根據(jù)id查部門信息锄开,查到null素标,人為拋出運(yùn)行時(shí)異常,讓Hystrix處理這種情況萍悴。
@RequestMapping(value="dept/get/{id}",method=RequestMethod.GET)
@HystrixCommand(fallbackMethod = "processHystrix_GET")
public Dept get(@PathVariable("id") Long id){
Dept dept = service.get(id);
if(null == dept){
throw new RuntimeException("該ID:"+id+"沒有對應(yīng)的部門信息");
}
return dept;
}
public Dept processHystrix_GET(@PathVariable("id") Long id){
return new Dept().setDeptno(id)
.setDname("該ID:"+id+"沒有對應(yīng)的信息头遭,null--@HystrixCommand")
.setDb_source("no this database in Mysql");
}
修改主啟動(dòng)類添加Hystrix支持
@SpringBootApplication
@EnableEurekaClient // 本服務(wù)啟動(dòng)后會(huì)注冊到Eureka服務(wù)注冊中心
@EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)
@EnableCircuitBreaker //對Hystrix熔斷機(jī)制的支持
public class DeptProvider8001_Hystrix_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
}
}
測試熔斷機(jī)制
啟動(dòng)三個(gè)Eureka集群寓免,啟動(dòng)服務(wù)主啟動(dòng)類DeptProvider8001_Hystrix_App,客戶端啟動(dòng)microservicecloud-consumer-dept-80计维,頁面訪問http://localhost/consumer/dept/get/112
服務(wù)降級
服務(wù)降級處理是在客戶端完成的袜香,與服務(wù)端沒有關(guān)系,在前面的服務(wù)熔斷中鲫惶,我們發(fā)現(xiàn)每一個(gè)業(yè)務(wù)方法都要寫一個(gè)processHystrix_方法蜈首,這樣就造成了很大耦合,根據(jù)Spring的學(xué)習(xí)欠母,我們可將processHystrix_改寫一個(gè)異常通知欢策。
修改microservicecloud-api工程
根據(jù)已有的DeptClientService接口,新建一個(gè)實(shí)現(xiàn)了FallbackFactory接口的類DeptClientServiceFallbackFactory
package com.luo.springcloud.service;
import java.util.List;
import org.springframework.stereotype.Component;
import com.luo.springcloud.entities.Dept;
import feign.hystrix.FallbackFactory;
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService>{
@Override
public DeptClientService create(Throwable arg0) {
return new DeptClientService() {
@Override
public List<Dept> list() {
return null;
}
@Override
public Dept get(long id) {
return new Dept().setDeptno(id)
.setDname("該ID:"+id+"沒有對應(yīng)的信息赏淌,Consumer客戶端提供的降級信息踩寇,此服務(wù)暫停使用")
.setDb_source("no this database in Mysql");
}
@Override
public boolean add(Dept dept) {
return false;
}
};
}
}
注意:不要忘記新類上添加@Component注解
修改microservicecloud-api
在DeptClientService接口在注解@FeignClient(value = "MICROSERVICECLOUD-DEPT")添加fallbackFactory屬性值
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
public Dept get(@PathVariable("id") long id);
@RequestMapping(value = "/dept/list",method = RequestMethod.GET)
public List<Dept> list();
@RequestMapping(value = "/dept/add", method = RequestMethod.POST)
public boolean add(Dept dept);
}
修改microservicecloud-consumer-dept-feign的Application.yml文件
server:
port: 80
feign:
hystrix:
enabled: true
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
測試服務(wù)降級
啟動(dòng)三個(gè)Eureka集群,microservicecloud-provider-dept-8001啟動(dòng)六水,microservicecloud-consumer-dept-feign啟動(dòng)俺孙,正常訪問http://localhost/consumer/dept/get/1測試,故意關(guān)停microservicecloud-provider-dept-8001掷贾,客戶端自己調(diào)用提示
服務(wù)監(jiān)控Hystrix Dashboard
Hystrix還提供了準(zhǔn)實(shí)時(shí)的調(diào)用監(jiān)控Hystrix Dashboard睛榄,Hystx會(huì)持續(xù)的記錄所有通過Hystrix發(fā)起的請求的執(zhí)行信息,并以統(tǒng)計(jì)報(bào)表的圖形的形式展示給用戶想帅,包括每秒執(zhí)行多少次請求多少成功多少失敗等场靴,對監(jiān)控內(nèi)容轉(zhuǎn)換為可視化界面。
新建microservicecloud-consumer-hystrix-dashboard監(jiān)控的一個(gè)微服務(wù)工程
POM.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.luo.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-consumer-hystrix-dashboard</artifactId>
<dependencies>
<!-- 自己定義的api -->
<dependency>
<groupId>com.luo.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改后立即生效博脑,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相關(guān) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- feign相關(guān) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- hystrix和 hystrix-dashboard相關(guān) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
</project>
application.yml文件
server:
port: 9001
主啟動(dòng)類DeptConsumer_DashBoard_App
@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_DashBoard_App.class, args);
}
}
微服務(wù)提供者添加監(jiān)控依賴配置
所有的Provider微服務(wù)提供類(8001,8002,8003)都需要監(jiān)控依賴配置憎乙,也就是pom文件添加如下依賴
<!-- actuator監(jiān)控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
監(jiān)控頁面測試
啟動(dòng)microservicecloud-consumer-hystrix-dashboard,訪問http://localhost:9001/hystrix,出現(xiàn)豪豬頁面
全部測試
啟動(dòng)3個(gè)Eureka集群叉趣,啟動(dòng)microservicecloud-provider-dept-hystrix-8001,啟動(dòng)了microservicecloud-consumer-hystrix-dashboard用來監(jiān)控8001服務(wù)提供者该押,訪問http://localhost:8001/hystrix.stream
觀察監(jiān)控窗口
訪問http://localhost:9001/hystrix疗杉,填寫監(jiān)控地址http://localhost:8001/hystrix.stream,時(shí)間2000,title:demo01,點(diǎn)擊按鈕
實(shí)心圓:兩種含義蚕礼,它通過顏色的變化代表了實(shí)例的健康程度烟具,健康色是從綠色<黃色<橙色<紅色遞減,該實(shí)心圓除了顏色的變化之外奠蹬,他的大小也會(huì)根據(jù)實(shí)例的請求流量發(fā)生變化朝聋,流量越大該實(shí)心圓就越大,所以通過實(shí)心圓的展示就可以在大量實(shí)例中快速的發(fā)現(xiàn) 故障實(shí)例和高壓力測試囤躁。