Hystrix&Feign

Hystrix

1,概念

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,可以保证一个服务出现故障时,不会导致整个系统出现雪崩效应,以提高分布式系统弹性;

作为“断路器”,在一个服务出现故障时,可以通过短路器监控,返回一个可以处理的响应结果,保证服务调用线程不会长时间被占用,避免故障蔓延。

雪崩 

当一个服务器中要同时处理多个请求时,当一个请求无法正确响应,请求超时。会将请求阻塞到该服务的线程池中,当线程池爆满出现故障,会导致整个服务中所有请求都无法正确响应,导致所有请求故障,出现雪崩。

2,服务降级

服务出现故障时,给故障服务降级到事先准备好的故障处理结果,将此结果返回给服务消费者,如:状态码 错误页面等

Hystrix为每一个请求分配一个线程池,当小线程池爆满的话会立刻被拒绝进行服务降级。

会导致请求失败,但是不会导致线程阻塞,最多影响这个依赖的线程池,不会影响其他线程池的正常工作。

触发服务降级的情况:

线程池满,请求超时,服务宕机

案例:

是服务的消费者担心请求服务时返回异常,所以要在消费者一方配置自己的降级处理,我们在消费方操作。例如:order请求user,在order方操作。

1,依赖导入


        
            org.springframework.cloud
            spring-cloud-starter-netflix-hystrix
        

2,Order启动类编写 添加熔断器注解

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//开启熔断注解
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

3,控制器编写 设置请求超时 降级熔断

@GetMapping("/{id}")
    @HystrixCommand(fallbackMethod="aa")//降级调用方法设置
    public Order getById(@PathVariable Long id){
        //order请求设置睡眠超时
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Order order = this.orderService.getById(id);
        /**
         *  http://user-service/user/ 其中user-service为动态表填写的应用名称
         *  会从注册中心拉取该名称的列表 为一个集合 会走负载策略 轮询等 访问不同服务
         */
        User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);
        order.setUser(user);
        return order;
    }
    //降级方法
    public Order aa(@PathVariable Long id){
        return new Order();
    }

4,请求时 请求时间过长 进行降级熔断 走降级方法 不会阻塞,会返回错误数据

Hystrix&Feign_第1张图片

5,当Order请求成功,order调用user时出现调用请求超时 进行降级处理

@GetMapping("/{id}")
    @HystrixCommand(fallbackMethod="bb")
    public User getById(@PathVariable Long id){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return this.userService.getById(id);
    }
    //降级方法
    public User bb(@PathVariable Long id){
        return new User();
    }

6,请求结果

Hystrix&Feign_第2张图片

3,服务熔断

服务熔断也称服务隔离,是服务降级的隔离措施。

在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。

开启熔断时机:

当一个规定时间窗口内,请求超时故障比率达到一个阈值,会开启熔断。

熔断恢复:

当过了设置的休眠期后,进入半开状态,允许一定的请求通过。 

熔断器有三个状态:
open 状态说明打开熔断,也就是服务调用方执行本地降级策略,不进行远程调用。
closed 状态说明关闭了熔断,这时候服务调用方直接发起远程调用。
half-open 状态,则是一个中间状态,当熔断器处于这种状态时候,直接发起远程调用。

 案例:

请求方法设置

@GetMapping("/{id}")
    @HystrixCommand(fallbackMethod="aa",
    commandProperties = {
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),//请求阈值
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),//休眠时间
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")//降级百分比
    })//降级调用方法设置  熔断设置
    public Order getById(@PathVariable Long id) {
        Order order = this.orderService.getById(id);
        /**
         *  http://user-service/user/ 其中user-service为动态表填写的应用名称
         *  会从注册中心拉取该名称的列表 为一个集合 会走负载策略 轮询等 访问不同服务
         */
        if(id==101){
            throw new RuntimeException("降级");
        }
        User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);
        order.setUser(user);
        return order;
    }

当请求编号102时,显示正确数据。

当请求101时,会进行降级,返回null数据。

重复请求101次数为请求阈值的降级百分比次数(10*60%)时,会进行休眠。

请求102时,也为null数据。

休眠10秒结束后,重新请求,数据为正确数据。

Feign

Feign 可以把 Rest 的请求进行隐藏,伪装成类似 SpringMVC Controller 一样。你不用再自己拼接url,拼接参数等等操作,一切都交给 Feign 去做。

使用Feign之前

@GetMapping("/{id}")
    public Order getById(@PathVariable Long id) {
        Order order = this.orderService.getById(id);
        if(id==101){
            throw new RuntimeException("降级");
        }
        User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);
        order.setUser(user);
        return order;
    }

使用之后

    @Autowired
    private UserFeignApi userFeignApi;
    @GetMapping("/{id}")
    public Order getById(@PathVariable Long id) {
        Order order = this.orderService.getById(id);
       
        User user = userFeignApi.getById(order.getUserId());
        
        order.setUser(user);
        return order;
    }

依赖导入


        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

新建一个子项目,用来管理feign组件

Hystrix&Feign_第3张图片

 将该组件进行pom依赖导入需要该组件的pom中,其他子项目即可使用该项目组件。


        
            com.zbx
            cloud_demo_comms
            1.0-SNAPSHOT
        

feign子项目中客户端接口编写

//配置请求地址 从注册中心中拉取order-service
@FeignClient(value = "order-service")
public interface OrderFeignApi {
    @GetMapping("/order/{id}")
    public Order getById(@PathVariable Long id);
}

相当于请求的地址通过feign去请求,只需要编写客户端接口,给定设置请求地址,从注册中心去拉取服务,然后再需要的地方注入该接口,调用方法即可。

Feign融合Hystix

案例:请求Order之后请求User,请求user时通过Feign进行服务降级与服务熔断。

1,user与order导入openFeign依赖

 
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

2,Order启动类

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//开启熔断注解
@EnableFeignClients//开启Feign
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

3,user启动类

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
@EnableFeignClients//开启Feign
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class,args);
    }
}

4,order配置文件application.yaml

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能
user-service: #配置负载均衡
  ribbon: # 改默认轮询为随机
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

5,user配置文件application.yaml

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能

6,orderController

@Autowired
    private UserFeignApi userFeignApi;
    @GetMapping("/{id}")
    public Order getById(@PathVariable Long id) {
        Order order = this.orderService.getById(id);
        User user = userFeignApi.getById(order.getUserId());
        order.setUser(user);
        return order;
    }

7,userFeignApi

//配置请求地址 从注册中心中拉取user-service value为服务实例id
@FeignClient(value = "user-service",fallback = UserFeignApiCallBack.class)
public interface UserFeignApi {
                //user为controller映射地址    
    @GetMapping("/user/{id}")
    public User getById(@PathVariable Long id);
}

8,UserFeignApiCallBack 

@Component
@Log4j2
public class UserFeignApiCallBack implements UserFeignApi {
    @Override
    public User getById(Long id) {
        log.warn("降级");
        return new User();
    }
}

9,访问user id为1

Hystrix&Feign_第4张图片

访问其他

Hystrix&Feign_第5张图片

你可能感兴趣的:(hystrix,java,运维)