2019年7月21日 星期日

Hystrix ( SpringCloud 2.x 五)

 Hystrix 就像保險絲一樣,可以處理異常


※server 端的異常


※1.複製 provider 後,增加 pom

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>


※這樣才有 @EnableCircuitBreaker、@HystrixCommand 可用

※順便改個 yml,instance.instance-id: bruceProvider-hystrix



※2.增加 provider-hystrix 的 controller

@RestController
public class TestController {
    @GetMapping("/testGet")
    public ApiBean get() {
        ApiBean ab = new ApiBean();
        ab.setId(1);
        ab.setName("xxx9001");
        return ab;
    }
    
    @HystrixCommand(fallbackMethod = "xxx")
    @GetMapping("/testHystrix/{id}")
    public ApiBean getXxxById(@PathVariable("id") Integer id) { // throws ParseException {
        if (id == 1) {
            ApiBean ab = new ApiBean();
            ab.setId(1);
            ab.setName("xxx9001");
            return ab;
        } else {
            throw new RuntimeException("耶!掛了");
            // throw new ParseException("xxx", -1);
        }
    }
    
    private ApiBean xxx(@PathVariable("id") Integer id) {
        ApiBean ab = new ApiBean();
        ab.setId(-1);
        ab.setName("沒有" + id);
        return ab;
    }
}


※只要拋異常都會被 xxx 方法所接收並回傳

※main 方法要加 @EnableCircuitBreake,但加 @EnableHystrix也可以,因為這個註解裡面也用 @EnableCircuitBreake,所以二選一即可

※如果很多方法都要用同一個,可以用全域的方式,如下:
一. 在方法上加 @HystrixCommand,但不寫 fallbackMethod
二. 在 class 上加 @DefaultProperties(defaultFallback="方法名") 即可
本來的 @HystrixCommand(fallbackMethod="方法名") 並不會被影響



※3.consumerFegin 也增加呼叫對應的方法


@RestController
public class ConsumerController {
    @Resource
    private MyService myService;
    
    @GetMapping("/xxx")
    public ApiBean get() {
        return myService.get();
    }
    
    @GetMapping("/ooo/{id}")
    public ApiBean getHystrix(@PathVariable("id") Integer id) {
        return myService.get(id);
    }
}





※4.api 也增加對應的方法

@FeignClient("PROVIDER1")
public interface MyService {
    @GetMapping("/testGet")
    ApiBean get();
    
    @GetMapping("/testHystrix/{id}")
    ApiBean get(@PathVariable("id") Integer id);
}


※使用 http://localhost/ooo/1 是正常的,但只要不是 1,都會出現 hystrix 提供的功能



※client 端的異常


由於 server 端的做法太過於高耦合了,在 client 端可以針對介面做處理,就算 server 端掛了,還是可以儘量的顯示友好的訊息

※1.因為要解耦,所以不要 @HystrixCommand,連 xxx 方法也不需要了,然後在 api 專案的 @FeignClient 有個 fallbackFactory,指定一個類別,然後做異常處理

@FeignClient(name = "PROVIDER1", fallbackFactory = MyFallbackFactory.class)
public interface MyService {
    @GetMapping("/testGet")
    ApiBean get();
    
    @GetMapping("/testHystrix/{id}")
    ApiBean get(@PathVariable("id") Integer id);
}





※2.異常處理類
@Component
public class MyFallbackFactory implements FallbackFactory<MyService> {
    @Override
    public MyService create(Throwable throwable) {
        return new MyService() {
            @Override
            public ApiBean get() {
                return null;
            }
    
            @Override
            public ApiBean get(Integer id) {
                ApiBean ab = new ApiBean();
                ab.setId(-1);
                ab.setName("沒有" + id);
                return ab;
            }
        };
    }
}


※記得要有 @Component 之類的註解,否則出錯時會出現 feign.FeignException: status 500 reading MyService#get(Integer) 的錯誤訊息


※3.cousumerfeign 的 yml 要加上 hystrix.enabled: true


※4.cousumerfeign 啟動類別
@SpringBootApplication
@ComponentScan({"controller", "service"})
@EnableEurekaClient
@EnableFeignClients("service")
public class ConsumerFeignMain {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignMain.class, args);
    }
}


※注意 @ComponentScan 要加上 api MyFallbackFactory 的包名,只要這個沒加或 yml 沒設定為 true,在啟動時都會出現 No fallbackFactory instance of type class service.MyFallbackFactory found for feign client PROVIDER1

※測試時和 server 端一樣,但是多一個,將 provider 關閉時,還是能出現 client 端設定的訊息,不管是不是 1 都是這個結果,所以訊息可以改得好一點的



※Hystrix 儀錶版


就是監控 hystrix 的

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>


※新增一個 module,然後增加 pom

※yml 很簡單,就是 port 而已,server.port: 9010



@SpringBootApplication
@EnableHystrixDashboard
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}


※啟動類別增加 @EnableHystrixDashboard

※訪問 http://localhost:9010/hystrix 就可看到帶刺的豬

測試:開啟 eureka -> provider_hystrix -> consumerFeign -> hystrix_dashboard

被監視的 provider_hystrix 要加 management.endpoints.web.exposure.include=*,否則點下 Monitor Stream 的按鈕時,中間會有 Unable to connect to Command Metric Stream. 的紅字,成功是 Loading ...

※以下沒試出來
1.上圖反白的網址是要監控的網址,所以是 provider_hystrix的,改成 http://localhost:9001/actuator/hystrix.stream,然後開啟新網頁貼上會看到網頁一直再跑,我試的結果居是出現問我要不要下載

2.但第1項是文字介面的,所以在上圖可打網址的地方貼上1的網址就可看到圖形介面

3.用 consumerFeign 訪問 provider_hystrix 即可看到 dashboard 的球變大

沒有留言:

張貼留言