一,Hystrix
SpringCloud體系中,自提供了Hystrix進行服務保護。對用戶端通路進行了服務降級,服務隔離以及服務熔斷等等處理。
二,環境搭建
Eureka實作基本服務調用環境搭建參考博文:SpringCloud:注冊中心——Eureka,本篇博文在基礎上進行處理
三,添加Maven坐标依賴
<!-- hystrix斷路器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
四,添加配置資訊
### 開啟hystrix斷路器
feign:
hystrix:
enabled: true
### hystrix啟動時間
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds : 1000
五,啟動類通過@Enable子產品開啟Hystrix
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
// 啟動Hystrix進行服務保護
@EnableHystrix
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class, args);
}
}
六,服務端代碼
package com.gupao.member.service.impl;
import com.gupao.api.service.IMemberServier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author pj_zhang
* @create 2019-01-09 23:48
**/
@RestController
public class MemberService implements IMemberServier {
@Value("${server.port}")
private Integer serverPort;
@Override
@RequestMapping("/getMember_1")
public String getMember_1() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("getMember_1 Thread Name : " + Thread.currentThread().getName());
return "MemberService.getMember_1, serverPort : " + serverPort;
}
@Override
@RequestMapping("/getMember_2")
public String getMember_2() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("getMember_2 Thread Name : " + Thread.currentThread().getName());
return "MemberService.getMember_2, serverPort : " + serverPort;
}
}
七,服務保護Service實作
1,服務保護分别通過服務通路和服務調用兩方面對Hystrix服務保護進行示範;差別在于,
* 服務通路:服務保護從浏覽器發起Http請求開始生效,目前服務代碼也在服務保護範圍内(這部分實作比較粗糙,暫時沒有找到統一處理方式)。這種服務保護機制對目前服務和服務端服務進行了統一保護,但同時也造成了耦合,如果本地業務已經超過Hystrix門檻值,則服務端接口根本不會調用;
* 服務調用:服務保護從開始調用服務端接口開始生效,目前服務代碼不在服務保護範圍内,這種實作提供了統一的實作的方式;但是這種方式相對來講隻對服務端進行了保護,目前服務依舊可能遭受之前提到的各種服務問題;
* 隻做示範,不要吐槽同時用,感覺同時用并不太好;向有更好方案的大神求方案!!!
2,基于服務通路的服務保護
package com.gupao.order.service.impl;
import com.gupao.api.service.IOrderService;
import com.gupao.order.feign.IMemberServiceFeign;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author pj_zhang
* @create 2019-01-10 0:04
**/
@RestController
public class OrderService implements IOrderService {
@Autowired
private IMemberServiceFeign memberServiceFeign;
/**
* 目前方法交由Hystrix進行服務保護
* @return
*/
@Override
@RequestMapping("/orderToMember_1")
// @HystrixCommand : Hystrix服務保護注解
// fallbackMethod : 觸發服務保護後, 執行後面指定方法内容
// orderToMemberFallback : 服務保護觸發後, 指定執行方法
@HystrixCommand(fallbackMethod = "orderToMemberFallback")
public String orderToMember_1() throws InterruptedException {
Thread.sleep(3000);
// Hystrix自動開啟服務隔離機制, 目前線程為Hystrix對目前服務建立的獨立的線程池中的線程
// 從下面示範中可以看到目前線程池與orderToMember_2方法的線程池不同
System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
return memberServiceFeign.getMember_1();
}
/**
* 服務保護觸發後, 執行該方法
*/
@RequestMapping("/orderToMemberFallback")
public String orderToMemberFallback() {
System.out.println("orderToMemberFallback Thread Name : " + Thread.currentThread().getName());
return "Hystrix進行服務保護, 系統錯誤!!!";
}
@Override
@RequestMapping("/orderToMember_2")
public String orderToMember_2() {
System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
return memberServiceFeign.getMember_2();
}
}
* 關注參數
-- Hystrix逾時時間為1S

-- 所有服務(包括服務端服務)睡眠時間為3S,則服務必定逾時
* 服務降級示範
-- 服務調用傳回結果,從下圖可以看到服務已經被降級處理
* 服務隔離示範
-- 服務降級示範線程号如下
-- 未交由Hystrix進行服務保護的接口線程号如下;可以看到服務交由Hystrix保護後,線程由Hystrix生成的線程池所建立,而未交由Hystrix保護的服務,線程則為Web容器自身的線程池建立
* 服務熔斷示範
-- 暫時無法示範,軟體不全,後續補全!!!
3,基于服務調用的服務保護 —— 基于Feign用戶端調用進行處理
* Feign用戶端通過聲明一個Feign接口進行服務調用,接口需要注解@FeignClient,其中@FeignClient自定義了fallback屬性,需要指定對應fallback處理類,進行對應服務保護處理,該指定類最好為目前Feign接口的實作類;處理後,所有Feign用戶端處理的接口都受Hystrix服務保護處理
* Feign接口
// 通過fallback屬性指定觸發服務保護後, 需要執行的類
@FeignClient(name = "app-itmayiedu-member", fallback = OrderServiceFallback.class)
public interface IMemberServiceFeign extends IMemberServier {
}
* fallback類,服務調用觸發Hystrix服務保護後,會對應執行該類中的服務對應方法,進行服務降級處理
package com.gupao.order.fallback;
import com.gupao.order.feign.IMemberServiceFeign;
import org.springframework.stereotype.Component;
/**
* @author pj_zhang
* @create 2019-01-22 21:37
**/
@Component
public class OrderServiceFallback implements IMemberServiceFeign {
@Override
public String getMember_1() {
System.out.println("getMember_1 Fallback Thread Name : " + Thread.currentThread().getName());
return "Hystrix進行服務保護, 系統錯誤!!!";
}
@Override
public String getMember_2() {
System.out.println("getMember_2 Fallback Thread Name : " + Thread.currentThread().getName());
return "Hystrix進行服務保護, 系統錯誤!!!";
}
}
* 服務降級示範,通過類聲明處理後,orderToMember_2接口就可以觸發Hystrix
-- 線程睡眠3S,示範這種服務保護方式對目前服務無影響,隻對調用端産生影響
@Override
@RequestMapping("/orderToMember_2")
public String orderToMember_2() throws InterruptedException {
Thread.sleep(3000);
System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
return memberServiceFeign.getMember_2();
}
* 服務隔離示範,從上圖可以看到,目前服務線程和fallback線程并不屬于同一個線程池
* 服務熔斷示範