概念:
線程隔離:將不同服務的請求用不同的線程池進行隔離,當某個服務不可用時請求只會耗盡該服務的線程池,但不會耗盡所有服務的線程池
服務降級:當某個服務不可用時,請求一直在等待(阻塞),則超過某個時間,自動返回該請求,告知一個友好提示,直到服務訪問可以成功為止
一 服務降級方式
注解:
@EnableCircuitBreaker
由於一個標准的springcloud項目必然有
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
因此可以使用:
@SpringCloudApplication
替代上述3條注解
在服務調用處添加:
1服務調用方法上添加:
@HystrixCommand(fallbackMethod = "fallBack")
2增加fallBack方法:
public String fallBack(Long id){
return "服務太擁擠了,請稍后再試!";
}
3要求FallBack方法和調用方法的返回值類型,參數列表必須一致
因此更改服務調用方法:
@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "fallBack")
public String queryById(@PathVariable("id") Long id){
String url = "http://user-server/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
//由於json格式就是字符串類型,因此此處可將User類型改為返回String類
更改后的完整代碼:
@RestController
@RequestMapping("consumer")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "fallBack")
public String queryById(@PathVariable("id") Long id){
String url = "http://user-server/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
public String fallBack(Long id){
return "服務太擁擠了,請稍后再試!";
}
}
由於有默認配置,因此此刻已經可以運行!
為了可以看到效果,在user-service服務提供代碼中只要增加線程睡眠,時間設定1500毫秒,即可觀察到效果
如果此類中有很多服務調用方法,為每個方法寫一個FallBack方法不合理,因此可以設置統一的FallBack方法:
在服務調用類上方加入:
@DefaultProperties(defaultFallback = "fallBack")
在方法需要返回錯誤信息的服務調用方法上直接加入注解即可:
@HystrixComman
由於此中方式,FallBack方法屬於統一錯誤處理方法,應當適用所有服務調用發放的錯誤調用,因此此種方式默認調用空參FallBack方法,所以改FallBack方法的參數列表為空參即可:
public String fallBack(){
return "服務太擁擠了,請稍后再試!";
}
改造后的完整代碼:
@RestController
@RequestMapping("consumer")
@DefaultProperties(defaultFallback = "fallBack")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id}")
@HystrixCommand
public String queryById(@PathVariable("id") Long id){
String url = "http://user-server/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
public String fallBack(){
return "服務太擁擠了,請稍后再試!";
}
}
以上,由於使用Hystrix默認超時時長設置(默認超時時長為:1s),實際使用時各個服務的調用可能不同,因此統一設置超時時長不一定適用所有服務調用方法
因此,可以需要手動設置超時時長,有兩種方法:
1 在服務調用方法中調整該服務調用方法的默認超時時長:
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
完整代碼:
@GetMapping("{id}")
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String queryById(@PathVariable("id") Long id){
String url = "http://user-server/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
這種方法可以針對每個服務調用方法設定超時時長
2 或者在配置文件中設置:
properties:
hystrix.commend.default.execution.isolation.thread.timeoutInMilliseconds=3000
hystrix.commend.user-service.execution.isolation.thread.timeoutInMilliseconds=5000
hystrix.commend.queryById.execution.isolation.thread.timeoutInMilliseconds=2000
yaml:
hystrix:
commend:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
user-service:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
queryById:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000
default部分為更改全局的默認超時時長
user-service部分為設置訪問user-service服務器的超時時長
queryById部分為設置queryById方法的超時時長
二 熔斷方式
之前使用服務降級方式,此種方式由於每個請求都要達到超時時間才返回,大大降低服務並發性,因此通常使用熔斷方式
熔斷:當大量請求無法正常訪問時(觸發服務降級中的超時時長),Hystrix則認為服務有問題,此時將會關閉服務,所有訪問該服務的請求全部直接返回錯誤,不再等待超時時長
即:觸發服務降級達到熔斷器的閥值則開啟熔斷
熔斷的3種狀態(針對熔斷器):
Open、Half Open、Closed
即:
熔斷器打開:當所有請求失敗的比例到達閥值(默認為50%,請求次數不低於20次),則會出發熔斷器打開狀態,所有請求直接回復錯誤
熔斷器半開:熔斷器打開狀態(默認5S),之后進入半開狀態,放部分請求通過,測試訪問是否成功,如成功則熔斷器轉入關閉狀態,如依舊不成功則熔斷器繼續進入打開狀態並再次進行倒計時
熔斷器關閉:所有請求可以正常訪問服務
circuitBreaker.requestVolumeThreshold=20
circuitBreaker.sleepWindowInMilliseconds=5000
circuitBreaker.errorThresholdPercentage=50
當主類上方使用@EnableCircuitBreaker注解,即熔斷器方式生效
注:通常只需要修改超時時長即可,因為超時時長默認1秒太短,網絡波動都有可能出發超時,其他設置通常不需要額外更改