在之前的18次文章中,我們實作了廣告系統的 廣告投放 廣告檢索 服務發現Eureka 服務調用Feign 網關路由Zuul 錯誤熔斷Hystrix Spring Cloud
,
業務功能,中間使用到了
,
以及
等
元件。
簡單調用關系:

Hystrix Dashboard
,顧名思義,從名字上我們就能看出來,它是監控的圖形化界面。 Hystrix 在服務中的使用
結合openfeign使用
在我們實際的項目當中,使用的最多的就是結合
FeignClient#fallback
和
Hystrix
一起來實作熔斷,我們看一下我們在
mscx-ad-feign-sdk
中的實作。
@FeignClient(value = "mscx-ad-sponsor", fallback = SponsorClientHystrix.class)
public interface ISponsorFeignClient {
@RequestMapping(value = "/ad-sponsor/plan/get", method = RequestMethod.POST)
CommonResponse<List<AdPlanVO>> getAdPlansUseFeign(@RequestBody AdPlanGetRequestVO requestVO);
@RequestMapping(value = "/ad-sponsor/user/get", method = RequestMethod.GET)
/**
* Feign 埋坑之 如果是Get請求,必須在所有參數前添加{@link RequestParam},不能使用{@link Param}
* 會被自動轉發為POST請求。
*/
CommonResponse getUsers(@RequestParam(value = "username") String username);
}
在上述代碼中,我們自定義了一個feignclient,并且給了這個client一個fallback的實作類:
@Component
public class SponsorClientHystrix implements ISponsorFeignClient {
@Override
public CommonResponse<List<AdPlanVO>> getAdPlansUseFeign(AdPlanGetRequestVO requestVO) {
return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get plan error.");
}
@Override
public CommonResponse getUsers(String username) {
return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get user error.");
}
}
這個fallback類實作了我們自定義的
ISponsorFeignClient
,那是因為fallback的方法必須和原始執行類的方法簽名保持一緻,這樣在執行失敗的時候,可以通過反射映射到響應的降級方法/容錯方法。
在
mscx-ad-search
服務中,我們通過注入
ISponsorFeignClient
來調用我們的
mscz-ad-sponsor
服務。
@RestController
@Slf4j
@RequestMapping(path = "/search-feign")
public class SearchFeignController {
/**
* 注入我們自定義的FeignClient
*/
private final ISponsorFeignClient sponsorFeignClient;
@Autowired
public SearchFeignController(ISponsorFeignClient sponsorFeignClient) {
this.sponsorFeignClient = sponsorFeignClient;
}
@GetMapping(path = "/user/get")
public CommonResponse getUsers(@Param(value = "username") String username) {
log.info("ad-search::getUsersFeign -> {}", JSON.toJSONString(username));
CommonResponse commonResponse = sponsorFeignClient.getUsers(username);
return commonResponse;
}
}
使用 HystrixCommand
HystrixCommand
其實Hystrix本身提供了一種直接在方法中應用的方式,就是使用
@ com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand
,我們看一下這個類的源碼:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {
...
/**
* Specifies a method to process fallback logic.
* A fallback method should be defined in the same class where is HystrixCommand.
* Also a fallback method should have same signature to a method which was invoked as hystrix command.
* for example:
* <code>
* @HystrixCommand(fallbackMethod = "getByIdFallback")
* public String getById(String id) {...}
*
* private String getByIdFallback(String id) {...}
* </code>
* Also a fallback method can be annotated with {@link HystrixCommand}
* <p/>
* default => see {@link com.netflix.hystrix.contrib.javanica.command.GenericCommand#getFallback()}
*
* @return method name
*/
String fallbackMethod() default "";
...
}
我們主要關注2個點:
-
表明目前的注解隻能應用在方法上面。@Target({ElementType.METHOD})
- 可直接定義
來保證容錯。這個方法有一個缺陷,就是必須和執行方法在同一個類檔案中,這就會造成我們的方法在實作的時候,顯得特别的備援和不夠優雅。fallbackMethod
以我們的
mscx-ad-search
中的廣告查詢為例:
@Service
@Slf4j
public class SearchImpl implements ISearch {
/**
* 查詢廣告容錯方法
*
* @param e 第二個參數可以不指定,如果需要跟蹤錯誤,就指定上
* @return 傳回一個空map 對象
*/
public SearchResponse fetchAdsFallback(SearchRequest request, Throwable e) {
System.out.println("查詢廣告失敗,進入容錯降級 : %s" + e.getMessage());
return new SearchResponse().builder().adSlotRelationAds(Collections.emptyMap()).build();
}
@HystrixCommand(fallbackMethod = "fetchAdsFallback")
@Override
public SearchResponse fetchAds(SearchRequest request) {
...
}
}
在我們請求出錯的時候,會轉到我們的fallback方法,這個實作是通過在應用啟動的時候,我們開始了
@EnableCircuitBreaker
注解,這個注解會通過AOP攔截所有的
HystrixCommand
方法,将
HystrixCommand
整合到springboot的容器中,并且将注解标注的方法放入hystrix的線程中,一旦失敗,通過反射調用fallback方法來實作。
建立dashboard project
上述代碼我們看了Hystrix實作熔斷的2種方式,接下來我們來實作請求監控的圖形化界面,建立
mscx-ad-dashboard
,Let's code.
依然遵從我們springboot項目的三部曲:
- 加依賴
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> <version>1.2.7.RELEASE</version> </dependency> <!--eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
- 加注解
/** * AdDashboardApplication for Hystrix Dashboard 啟動類 * * @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a> * @since 2019/8/15 */ @SpringBootApplication @EnableDiscoveryClient @EnableHystrixDashboard public class AdDashboardApplication { public static void main(String[] args) { SpringApplication.run(AdDashboardApplication.class, args); } }
- 改配置
server: port: 1234 spring: application: name: mscx-ad-dashboard eureka: client: service-url: defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ management: endpoints: web: exposure: include: "*"`
直接啟動,可以看到如下頁面:
添加要監控的服務位址: