本文節選自《瘋狂Spring Cloud微服務架構實戰》html
京東購買地址:https://item.jd.com/12256011.htmljava
噹噹網購買地址:http://product.dangdang.com/25201393.htmlgit
Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993web
Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383spring
先編寫一個簡單的Hello World程序,展現Hystrix的基本做用。前面的章節會單獨講解Hystrix框架,後面章節纔會整合Spring Cloud一塊兒使用。apache
使用Spring Boot的spring-boot-starter-web項目,創建一個普通的Web項目,發佈兩個測試服務用於測試,控制器的代碼請見代碼清單6-1。網絡
代碼清單6-1:架構
codes\06\6.2\first-hystrix-server\src\main\java\org\crazyit\cloud\MyController.javaapp
@RestController public class MyController { @GetMapping("/normalHello") public String normalHello(HttpServletRequest request) { return "Hello World"; } @GetMapping("/errorHello") public String errorHello(HttpServletRequest request) throws Exception { // 模擬須要處理10秒 Thread.sleep(10000); return "Error Hello World"; } }
一個正常的服務,另一個服務則須要等待10秒纔有返回。本例的Web項目對應的代碼目錄爲codes\06\6.2\first-hystrix-server,啓動類是ServerApplication。框架
結合Hystrix來請求Web服務,可能與原來的方式不太同樣。新建項目「first-hystrix-client」,在pom.xml中加入如下依賴:
<dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <version>1.7.25</version> <artifactId>slf4j-log4j12</artifactId> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>
本書Spring Cloud所使用的Hystrix版本爲1.5.12,咱們也使用與其一致的版本。客戶端項目除了要使用Hystrix外,還會使用HttpClient模塊訪問Web服務,所以要加入相應的依賴。新建一個命令類,實現請見代碼清單6-2。
代碼清單6-2:
codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\HelloCommand.java
public class HelloCommand extends HystrixCommand<String> { private String url; CloseableHttpClient httpclient; public HelloCommand(String url) { // 調用父類的構造器,設置命令組的key,默認用來做爲線程池的key super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); // 建立HttpClient客戶端 this.httpclient = HttpClients.createDefault(); this.url = url; } protected String run() throws Exception { try { // 調用 GET 方法請求服務 HttpGet httpget = new HttpGet(url); // 獲得服務響應 HttpResponse response = httpclient.execute(httpget); // 解析並返回命令執行結果 return EntityUtils.toString(response.getEntity()); } catch (Exception e) { e.printStackTrace(); } return ""; } }
新建運行類,執行HelloCommand,如代碼清單6-3所示。
代碼清單6-3:
codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\HelloMain.java
public class HelloMain { public static void main(String[] args) { // 請求正常的服務 String normalUrl = "http://localhost:8080/normalHello"; HelloCommand command = new HelloCommand(normalUrl); String result = command.execute(); System.out.println("請求正常的服務,結果:" + result); } }
正常狀況下,直接調用HttpClient的API來請求Web服務,而前面的命令類與運行類,則經過命令來執行調用的工做。在命令類HelloCommand中,實現了父類的run方法,使用HttpClient調用服務的過程,都放到了該方法中。運行HelloMain類,能夠看到,結果與日常調用Web服務無異。接下來,測試使用Hystrix的狀況下調用有問題的服務。
假設咱們所調用的Hello服務發生故障,致使沒法正常訪問,那麼對於客戶端來講,如何自保呢?本例將調用延時的服務,爲客戶端設置回退方法。修改HelloCommand類,加入回退方法,請見代碼清單6-4。
代碼清單6-4:
codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\HelloCommand.java
protected String getFallback() { System.out.println("執行 HelloCommand 的回退方法"); return "error"; }
在運行類中,調用發生故障的服務,請見代碼清單6-5。
代碼清單6-5:
codes\06\6.2\first-hnystrix-client\src\main\java\org\crazyit\cloud\HelloErrorMain.java
public class HelloErrorMain { public static void main(String[] args) { // 請求異常的服務 String normalUrl = "http://localhost:8080/errorHello"; HelloCommand command = new HelloCommand(normalUrl); String result = command.execute(); System.out.println("請求異常的服務,結果:" + result); } }
運行HelloErrorMain類,輸出以下:
執行 HelloCommand 的回退方法 請求異常的服務,結果:error
根據結果可知,回退方法被執行。本例中調用的「errorHello」服務,會阻塞10秒纔有返回。默認狀況下,若是調用的Web服務沒法在1秒內完成,那麼將會觸發回退。
回退更像是一個備胎,當請求的服務沒法正常返回時,就調用該「備胎」的實現。這樣作,能夠很好的保護客戶端,服務端所提供的服務受網絡等條件的制約,若是有服務真的須要10秒才能返回結果,而客戶端又沒有容錯機制,後果就是,客戶端將一直等待返回,直到網絡超時或者服務有響應,而外界會一直不停地發送請求給客戶端,最終致使的結果就是,客戶端因請求過多而癱瘓。
本文節選自《瘋狂Spring Cloud微服務架構實戰》
Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993
Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383