瘋狂Spring Cloud連載(19)Spring Cloud整合Hystrix
19 Spring Cloud中使用Hystrix
Hystrix主要用於保護呼叫服務的一方,如果被呼叫的服務發生故障,符合一定條件,就開啟斷路器,對呼叫的程式進行隔離。在開始講述本章的內容前,先準備測試專案,本章例子所使用的專案如下:
spring-hystrix-server:Eureka伺服器,埠為8761,程式碼目錄codes\06\6.4\spring-hystrix-server。
spring-hystrix-provider:服務提供者,本例只需要啟動一個例項,埠為8080,預設提供“/person/{personId}”服務,根據personId引數返回一個Person例項
spring-hystrix-invoker:服務呼叫者,9000埠,程式碼目錄codes\06\6.4\spring-hystrix-invoker。
整合Hystrix
為服務呼叫者(spring-hystrix-invoker)專案新增依賴,新增後的依賴如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<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-hystrix</artifactId>
</dependency>
在服務呼叫者的應用啟動類中,加入啟用斷路器的註解,請見以下程式碼片斷:
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class InvokerApplication {
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(InvokerApplication.class, args);
}
}
新建服務類,在服務方法中呼叫服務,請見程式碼清單6-17。
程式碼清單6-17:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\PersonService.java
@Component
public class PersonService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "getPersonFallback")
public Person getPerson(Integer id) {
//使用RestTemplate呼叫Eureka服務
Person p = restTemplate.getForObject(
"http://spring-hystrix-provider/person/{personId}",
Person.class, id);
return p;
}
/**
*回退方法,返回一個預設的Person
*/
public Person getPersonFallback(Integer id) {
Person p = new Person();
p.setId(0);
p.setName("Crazyit");
p.setAge(-1);
p.setMessage("request error");
return p;
}
}
服務類中注入了RestTemplate,服務方法使用了@HystrixCommand註解進行修飾,並且配置了回退方法。@HystrixCommand註解由Hystrix的“javanica”專案提供,該專案主要是為了簡化Hystrix的使用。被@HystrixCommand修飾的方法,Hystrix(javanica)會使用AspectJ對其進行代理,Spring會將相關的類轉換為Bean放到容器中,在Spring Cloud中,我們無需過多關心Hystrix的命令管理。
接下來,編寫控制器,呼叫服務類的方法,請見程式碼清單6-18。
程式碼清單6-18:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\InvokerController.java
@RestController
@Configuration
public class InvokerController {
@Autowired
private PersonService personService;
@RequestMapping(value = "/router/{personId}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public Person router(@PathVariable Integer personId) {
Person p = personService.getPerson(personId);
return p;
}
}
控制器實現較為簡單,直接注入PersonService,呼叫方法即可,按以下步驟啟動叢集:
啟動“spring-hystrix-server”,本例中配置埠為8761。
啟動“spring-hystrix-provider”,啟動一個例項,埠為8080。
啟動“spring-hystrix-invoker”,埠為9000。
{"id":1,"name":"Crazyit","age":33,"message":"http://localhost:8080/person/1"}
停止服務提供者(spring-hystrix-provide),即停止8080埠,再訪問9000埠的地址,輸出如下:
{"id":0,"name":"Crazyit","age":-1,"message":"request error"}
根據輸出可知,由於呼叫失敗,觸發了回退方法。
命令配置
Spring Cloud中使用@HystrixCommand來宣告一個命令,命令的相關配置,也可以在該註解中進行,以下的程式碼片斷,配置了幾個屬性:
/**
*測試配置,對3個key進行命名
*設定命令執行超時時間為1000毫秒
*設定命令執行的執行緒池大小為1
*/
@HystrixCommand(
fallbackMethod="testConfigFallback", groupKey="MyGroup",
commandKey="MyCommandKey", threadPoolKey="MyCommandPool",
commandProperties={
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "1000")
},
threadPoolProperties={
@HystrixProperty(name = "coreSize",
value = "1")
})
除了以上的幾個配置外,@HystrixCommand註解還可以使用ignoreExceptions來處理異常的傳播,請見以下程式碼片斷:
/**
*聲明瞭忽略MyException,如果方法丟擲MyException,則不會觸發回退
*/
@HystrixCommand(ignoreExceptions = {MyException.class},
fallbackMethod="testExceptionFallBack")
public String testException() {
throw new MyException();
}
Hystrix的命令、執行緒配置較多,由於篇幅所限,本小節僅簡單地列舉幾個,讀者可舉一反三,按需要進行配置。
預設配置
對於一些預設的配置,例如命令組的key等,可以使用@DefaultProperties註解,這樣就減少了@HystrixCommand註解的程式碼量。以下程式碼片斷展示如何使用@DefaultProperties:
@DefaultProperties(groupKey="GroupPersonKey")
public class PersonService {
@HystrixCommand // group key將使用“GroupPersonKey”
public String hello() {
return "";
}
}
除了定義GroupKey外,還支援@HystrixCommand的其餘配置,例如執行緒屬性、命令屬性等。