第十九章 springboot + hystrix(1)


hystrix是微服務中用於做熔斷、降級的工具。

作用:防止因為一個服務的調用失敗、調用延時導致多個請求的阻塞以及多個請求的調用失敗。

1、pom.xml(引入hystrix-core包)

1          <!-- hystrix -->   
2         <dependency>
3             <groupId>com.netflix.hystrix</groupId>
4             <artifactId>hystrix-core</artifactId>
5             <version>1.5.2</version>
6         </dependency>
View Code

2、application.properties

1 #hystrix
2 hystrix.timeoutInMillions = 3000
View Code

說明:設置hystrix屬性,如上是"服務調用超時時間",其他屬性設置見:https://github.com/Netflix/Hystrix/wiki/Configuration

3、HyStrixProperties

 1 package com.xxx.firstboot.hystrix;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 import org.springframework.stereotype.Component;
 5 
 6 import lombok.Getter;
 7 import lombok.Setter;
 8 
 9 @Getter @Setter
10 @Component
11 @ConfigurationProperties(prefix = "hystrix")
12 public class HyStrixProperties {
13     private int timeoutInMillions;
14 }
View Code

4、MyHyStrixCommand

 1 package com.xxx.firstboot.hystrix;
 2 
 3 import org.slf4j.Logger;
 4 import org.slf4j.LoggerFactory;
 5 
 6 import com.netflix.hystrix.HystrixCommand;
 7 import com.squareup.okhttp.OkHttpClient;
 8 import com.squareup.okhttp.Request;
 9 import com.squareup.okhttp.Response;
10 
11 public class MyHystrixCommand extends HystrixCommand<Response> {
12     private static final Logger LOGGER = LoggerFactory.getLogger(MyHystrixCommand.class);
13     private String url;
14 
15     public MyHystrixCommand(Setter setter, String url) {
16         super(setter);
17         this.url = url;
18     }
19 
20     @Override
21     protected Response run() throws Exception {
22         LOGGER.info("服務正被調用,當前線程:'{}'", Thread.currentThread().getName());
23         Request request = new Request.Builder().url(url).build();
24         return new OkHttpClient().newCall(request).execute();
25     }
26 
27     @Override
28     public Response getFallback() {
29         LOGGER.error("服務調用失敗,service:'{}'");
30         return null;
31     }
32 }
View Code

說明:

  • 該類是最關鍵的一個類。
  • 繼承HystrixCommand<T>
  • 添加構造器,注意:無法添加無參構造器,因此該類無法作為spring的bean來進行管理
  • 程序開始時執行run(),當執行發生錯誤或超時時,執行getFallback()

5、HyStrixUtil

 1 package com.xxx.firstboot.hystrix;
 2 
 3 import java.util.concurrent.ExecutionException;
 4 import java.util.concurrent.Future;
 5 
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.stereotype.Component;
 8 
 9 import com.netflix.hystrix.HystrixCommand.Setter;
10 import com.netflix.hystrix.HystrixCommandGroupKey;
11 import com.netflix.hystrix.HystrixCommandKey;
12 import com.netflix.hystrix.HystrixCommandProperties;
13 import com.squareup.okhttp.Response;
14 
15 @Component
16 public class HystrixUtil {
17 
18     @Autowired
19     private HyStrixProperties hp;
20     
21     public Response execute(String hotelServiceName, 
22                             String hotelServiceMethodGetHotelInfo, 
23                             String url) throws InterruptedException, ExecutionException {
24         Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(hotelServiceName));//被調用服務
25         setter.andCommandKey(HystrixCommandKey.Factory.asKey(hotelServiceMethodGetHotelInfo));//被調用服務的一個被調用方法
26         setter.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(hp.getTimeoutInMillions()));
27         return new MyHystrixCommand(setter, url).execute();//同步執行
28 //        Future<Response> future = new MyHystrixCommand(setter, url).queue();//異步執行
29 //        return future.get();//需要時獲取
30     }
31 
32 }
View Code

說明:

  • hystrix的執行方式
    • 同步執行:超時時間起作用
    • 異步執行:超時時間不起作用(1.4.0之前的版本,在調用get()的時候開始計時起作用)
  • hystrix的隔離級別
    • HystrixCommandGroupKey:這個的名稱設置為一個被調用的服務,eg.hotelService,所有這個服務下的方法都用同一個線程池(前提是沒有配置ThreadPoolKey)
    • HystrixCommandKey:這個名稱通常是被調用服務的一個方法的名字(實際上就是被調用服務某一個controller中的一個對外方法),eg.getHotelInfo()
    • ThreadPoolKey:這個用的很少,除非一個被調用服務中的有些被調用方法快、有的被調用方法慢,這樣的話,就需要分別使用一個ThreadPoolKey,為每一個方法單獨分配線程池

6、application.properties

1 service.hotel.name = hotelService
2 service.hotel.method.getHotelInfo = getHotelInfo 
View Code

說明:定義被調用服務的服務名和被調用方法名,當然服務名也可以使用被調用服務的controller的簡單類名。

7、HystrixController

 1 package com.xxx.firstboot.web;
 2 
 3 import java.io.IOException;
 4 import java.util.concurrent.ExecutionException;
 5 
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.beans.factory.annotation.Value;
 8 import org.springframework.web.bind.annotation.RequestMapping;
 9 import org.springframework.web.bind.annotation.RequestMethod;
10 import org.springframework.web.bind.annotation.RequestParam;
11 import org.springframework.web.bind.annotation.RestController;
12 
13 import com.squareup.okhttp.Response;
14 import com.xxx.firstboot.hystrix.HystrixUtil;
15 
16 @RestController
17 @RequestMapping("/hystrix")
18 public class HystrixController {
19 
20     @Value("${service.hotel.url}")
21     private String HOTEL_URL;
22 
23     @Value("${service.hotel.name}")
24     private String hotelServiceName;
25     
26     @Value("${service.hotel.method.getHotelInfo}")
27     private String hotelServiceMethodGetHotelInfo;
28     
29     @Autowired
30     private HystrixUtil hystrixUtil;
31 
32     @RequestMapping(value = "/firstHystrix", method = RequestMethod.GET)
33     public String getHotelInfo(@RequestParam("id") int id, @RequestParam("name") String name) {
34         String url = String.format(HOTEL_URL, id, name);
35         Response response = null;
36         try {
37             response = hystrixUtil.execute(hotelServiceName, hotelServiceMethodGetHotelInfo, url);
38             if (response != null) {
39                 return response.body().string();
40             }
41         } catch (IOException e) {
42             e.printStackTrace();
43         } catch (InterruptedException e) {
44             e.printStackTrace();
45         } catch (ExecutionException e) {
46             e.printStackTrace();
47         } finally {
48             if (response != null && response.body() != null) {
49                 try {
50                     response.body().close();// 資源關閉
51                 } catch (IOException e) {
52                     e.printStackTrace();
53                 }
54             }
55         }
56         return "獲取酒店信息失敗";
57     }
58 
59 }
View Code

說明:

  • 使用@value做屬性注入,假設我們是在consul上配置了application.properties內容,當修改了屬性文件的內容后,該服務也必須重啟,因為@value只讀一次(沒測過,同事說的)
  • 使用spring的Environment進行注入,當修改了屬性文件的內容后,服務不需要重啟,會每五分鍾重新刷一次(沒測過,同事說的)
  • 使用boot構建一個屬性收集類,如上邊的HyStrixProperties類,不知道是否需要重啟(沒測過)

有測過的朋友和我講一下,我有時間也會測一下。

下邊是被調用服務的代碼:

8、HotelController

 1 @RestController
 2 @RequestMapping("/hotel")
 3 @Api("HotelController相關api")
 4 public class HotelController {
 5     @ApiOperation("獲取酒店Hotel信息:getHotelInfo")
 6     @RequestMapping(value="/getHotelInfo",method=RequestMethod.GET)
 7     public Hotel getHotelInfo(@RequestParam("id") int id, @RequestParam("name") String name) {
 8 //        try {
 9 //            TimeUnit.MILLISECONDS.sleep(2000);//用於測試超時
10 //        } catch (InterruptedException e) {
11 //            e.printStackTrace();
12 //        }
13         return new Hotel(id, name);
14     }
15 }
View Code

測試:啟動被調用服務-->啟動調用服務

 

參考:

http://blog.csdn.net/xiaoyu411502/article/details/50601687 官方的中文總結

https://stonetingxin.gitbooks.io/hystrix/content/ 基本上是官方的中文翻譯

https://github.com/Netflix/Hystrix/wiki/Configuration hystrix配置介紹

http://blog.vicoder.com/hystrix-configuration/ 配置介紹

http://www.insaneprogramming.be/blog/2014/08/19/hystrix-spring-boot/ boot集成hystrix


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM