spring cloud (七) 熔断机制hystrix

一、hystrix简述

Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这一组件进行了整合。在微服务架构中,一个请求需要调用多个服务是非常常见的,如下图:

 

  • 雪崩效应

如上图可以看出微服务是非常多的,同时可能出现多个微服务之间进行复杂的通信,那么如果有一个服务出现问题,就会引起雪崩效应,导致整个系统瘫痪

spring cloud hystrix提供了一个类似于保险丝的作用,当服务不可用的时候,hystrix打开断路器,不再进行服务通信。从而保证自身服务的可用性。

 

  • 服务降级

服务降级就是在系统高并发的情况下,可以将一些边缘服务进行降级(服务暂停),将资源优先供给核心服务的处理。

例如:在每年年底的时候,12306网站都是最繁忙的时候,那么这个时候细心的朋友就会发现一个情况:当到了指定的时间,大家开始抢票的时候,如果你不抢票,而是查询一些冷门的车次,你可能会发现票有时候查询不出来。因为这个时候比较冷门的服务,由于不太受到过多关注,可以考虑将服务降级。

二、ribbon整合hystrix使用

1.添加依赖

<!--hystrix jar包-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2.在启动类添加注解@EnableCircuitBreaker开启hystrix

@SpringBootApplication
@MapperScan("com.wangcongming")
@EnableEurekaClient
@EnableCircuitBreaker
public class OrderSystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderSystemApplication.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        //连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
        httpRequestFactory.setConnectionRequestTimeout(3000);
        //设置连接超时时间
        httpRequestFactory.setConnectTimeout(3000);
        //设置读超时时间,即请求处理超时时间
        httpRequestFactory.setReadTimeout(3000);
        // 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。
        // clientHttpRequestFactory.setBufferRequestBody(false);
        return new RestTemplate(httpRequestFactory);
    }
}

3.开发示例

package com.wangcongming.shop.order.service.impl;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.wangcongming.shop.order.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class UserServiceImpl implements UserService{

    @Autowired
    private RestTemplate restTemplate;

    /**
     * @HystrixCommand注解用于开启断路器,fallbackMethod方法为当断路器打开时执行此方法
     * commandProperties属性中的@HystrixProperty用来指定熔断机制执行策略指定,有两种策略THREAD|SEMAPHORE
     * 默认使用THREAD,官方推荐使用THREAD,也就是不指定commandProperties
     * 以上操作,同样适用于使用@SessionScope或@RequestScope的时候。
     * 当抛出“无法找到范围内的上下文”的运行时异常,就需要执行这些操作。
     * 所以正常情况不需要配置这些数据
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "findByIdFallback",
            commandProperties = {@HystrixProperty(name="execution.isolation.strategy",
                    value="SEMAPHORE")})
    public String getUserById(String id){

        ResponseEntity<String> entity = restTemplate.getForEntity("http://user-system/user/findUser/" + id, String.class);
        String body = entity.getBody();
        return body;
    }

    public String findByIdFallback(String id){
        return id;
    }
}

如代码中所示,通过注解@HystrixCommand来指明fallback方法(当hystrix打开或者调用异常时执行的方法)和一些其他属性。

三、feign整合hystrix

1.添加依赖

<!--hystrix jar包-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2.修改配置文件

在配置文件中添加开启feign对hystrix的支持

#Dalston SR1(待定)之后的版本默认关闭hystrix对feign的支持,如果想要使用fallback功能这里必须启用
feign:
    hystrix:
        enabled: true

3.示例

package com.wangcongming.shop.score.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @author wangcongming
 * @Package com.wangcongming.shop.score.entity
 * @Description: feign调用
 *              @RequestParam @RequestBody @RequestHeader
 * @date 2018/5/19 14:24
 */
@FeignClient(name = "user-system",fallback = UserClientFallBack.class)
public interface UserClient {

    @RequestMapping(value="/user/findUser/{id}", method = RequestMethod.GET)
    public String getUserInfo(@PathVariable("id") String id);

    @RequestMapping(value="/user/addScore", method = RequestMethod.GET)
    public String update(@RequestParam("uid") String uid,@RequestParam("score") String score);
}
package com.wangcongming.shop.score.feign;

import org.springframework.stereotype.Component;

/**
 * 当UserClient中的feign调用失败或超时时,会调用该实现类的方法
 */
@Component
public class UserClientFallBack implements UserClient {

    @Override
    public String getUserInfo(String id) {
        System.out.println("------------------" + id + "**********************");
        String ss = id;
        return null;
    }

    @Override
    public String update(String uid, String score) {
        return null;
    }
}

需要注意的是fallback指定的类一定要添加@Component将其加入到spring 容器

4.针对某一个@FeignClient禁用hystrix

修改configuration配置即可,代码示例如下

package com.wangcongming.shop.score.feign;

import com.wangcongming.shop.score.config.FeignOneConfiguration;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;

/**
 * @author wangcongming
 * @Package com.wangcongming.shop.score.entity
 * @Description: feign调用
 * @date 2018/5/19 14:24
 */
@FeignClient(name = "user-system2",configuration = FeignOneConfiguration.class)
public interface UserClient2 {

    @RequestLine("GET /user/findUser/{id}")
    public String getUserInfo(@Param("id") String id);
}
package com.wangcongming.shop.score.config;

import com.wangcongming.annotation.ExcludeFilter;
import feign.Contract;
import feign.Feign;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
@ExcludeFilter
public class FeignOneConfiguration {

    @Bean
    public Contract feignContract(){
        return new feign.Contract.Default();
    }

    /**
     * 查看org.springframework.cloud.netflix.feign.FeignClientsConfiguration可以发现
     * @Bean
     * @Scope("prototype")
     * @ConditionalOnMissingBean
     * @ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false)
     * public Feign.Builder feignHystrixBuilder() {
     *      return HystrixFeign.builder();
     * }
     * 可以看出当feign.hystrix.enabled配置为true时,默认开启HystrixFeign.builder()
     * @return
     */
    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return Feign.builder();
    }
}

需要注意的是,一定要在入口类bean扫描时,将此类排除在外。具体代码如下

package com.wangcongming.shop.score;

import com.wangcongming.annotation.ExcludeFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * @author wangcongming
 * @Package com.wangcongming.shop.score
 * @Description:
 * @date 2018/5/18 14:46
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@ComponentScan(basePackages = { "com.wangcongming" },excludeFilters = {
        @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                value = ExcludeFilter.class
        )
})
public class ScoreApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScoreApplication.class,args);
    }
}

其中ExcludeFilter注解为自定义注解,用于标明需要排除在组件扫描之外的类

推荐一套spring cloud学习视频 下载地址:https://download.csdn.net/download/linhui258/10525913

猜你喜欢

转载自blog.csdn.net/linhui258/article/details/80877077