断路器hystrix原理及使用

hystrix原理图.png

原理

在微服务架构中,服务之间形成调用链路,链路中的任何一个服务提供者都可能面临着相应超时、宕机等不可用的情况,在高并发的情况下,这种情况会随着并发量的上升恶化,形成“雪崩效应”,而断路器hystrix正是用来解决这一个问题的组件。

断路器基本原理为:

  • 正常情况下,断路器关闭,服务消费者正常请求微服务
  • 一段事件内,失败率达到一定阈值(比如50%失败,或者失败了50次),断路器将断开,此时不再请求服务提供者,而是只是快速失败的方法(断路方法)
  • 断路器打开一段时间,自动进入“半开”状态,此时,断路器可允许一个请求方法服务提供者,如果请求调用成功,则关闭断路器,否则继续保持断路器打开状态。

断路器hystrix是保证了局部发生的错误,不会扩展到整个系统,从而保证系统的即使出现局部问题也不会造成系统雪崩。

本文示例代码:helloworld+helloworldfeign+hello+world

主要见springcloud-demo下hello/world/helloworld/helloworldfeign项目。

配置/使用

下面讲解在restTemplate和feign中断路器的配置和使用步骤

restTemplate+ribbon整合Hystrix

  • 引入hystrix依赖
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
   </dependency>

虽然Eureka依赖了ribbon,ribbon依赖了hystrix-core,但还是要引用了上面的maven依赖,因为下面用到的@HystrixCommand注解用到了hystrix-javanica包

  • 启动类加上@EnableCircuitBreaker注解(@EnableHystrix也可以)
  • 修改HelloWorldController的入口请求方法
@GetMapping("/message")
    @HystrixCommand(fallbackMethod = "getMessageFallback")
    public HelloworldMessage getMessage() {
        HelloMessage hello = getMessageFromHelloService();
        WorldMessage world = getMessageFromWorldService();
        HelloworldMessage helloworld = new HelloworldMessage();
        helloworld.setHello(hello);
        helloworld.setWord(world);
        log.debug("Result helloworld message:{}", helloworld);
        return helloworld;
    }

    /**
     * 断路方法
     * @return
     */
    public HelloworldMessage getMessageFallback(){
       HelloMessage helloMessage=new HelloMessage();
       helloMessage.setName("hello");
       helloMessage.setMessage("error occurs");

       WorldMessage worldMessage=new WorldMessage();
       worldMessage.setMessage("world error occurs");
       HelloworldMessage helloworldMessage=new HelloworldMessage();
       helloworldMessage.setHello(helloMessage);
       helloworldMessage.setWord(worldMessage);
       return helloworldMessage;
    }

通过@HystrixCommand注解的fallbackMethod指向断路方法,该方法会在调用hello服务或者world服务失败时被调用。
@HystrixCommand 注解还可以配置超时事件等其他属性。

  • 测试

1)依次启动eureka server:discovery/trace/hello/world/helloword项目
2)在浏览器输入地址http:\\localhost:8020/message,则返回正确的结果
3)停止hello项目,再次输入上述地址,则执行断路器中的方法。

feign下整合Hystrix

  • feign禁用Hystrix
    在Spring Cloud中,只要Hystrix在项目的classpath中,Feign就会用断路器包裹Feign客户端的所有方法,如果要禁用Hystrix则可以通过自定义feign的配置来解决。
@Configuration
public class FeignConfiguration{
     @Bean
     @Scope("prototype")
     public Feign Builder feignBuilder(){
           return Feign.builder();
     }
}

要禁用Hystrix的接口引用该配置即可

@FeignClient(name="hello",configuration=FeignConfiguration.class)
public interface HelloService{
    ......
}

feign使用Hystrix

  • 启用Hystrix
    默认情况下feign已经整合了Hystrix,在配置文件中开启即可(本人用的的Dalston.SR2版本的Spring Cloud,需要在配置文件开启)
feign:
  hystrix:
    enabled: true
  • 接口指定回退类
    在HelloService中修改FeignClient类,指定fallback的类
package com.example.helloworldfeign.service;

import com.example.helloworldfeign.model.HelloMessage;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author billjiang 475572229@qq.com
 * @create 17-8-23
 */
@FeignClient(value="hello",fallback = HelloServiceFallback.class)
public interface HelloService {

    @GetMapping("/message")
    HelloMessage hello();


}

实现了接口fallback的类的实现:

package com.example.helloworldfeign.service;

import com.example.helloworldfeign.model.HelloMessage;
import org.springframework.stereotype.Component;

/**
 * @author billjiang 475572229@qq.com
 * @create 17-8-28
 */
@Component
public class HelloServiceFallback implements HelloService {
    @Override
    public HelloMessage hello() {
        HelloMessage helloMessage=new HelloMessage();
        helloMessage.setName("hello");
        helloMessage.setMessage("error occurs");
        return helloMessage;
    }
}

world项目同上

  • 测试

1)依次启动eureka server:discovery/trace/hello/world/helloword-feing项目
2)在浏览器输入地址http:\\localhost:8030/message,则返回正确的结果
3)停止hello项目,再次输入上述地址,则执行断路器中的方法。

查看断路器错误日志
如果要查看详细的断路器的日志,可以通过注解@FeignClient的fallbackFactory来实现,如下代码所示:


import com.example.helloworldfeign.model.HelloMessage;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author billjiang 475572229@qq.com
 * @create 17-8-23
 */
@FeignClient(value="hello",fallbackFactory = HelloServiceFallbackFactory.class)
public interface HelloService {

    @GetMapping("/message")
    HelloMessage hello();


}

HelloServiceFallbackFactory类:

package com.example.helloworldfeign.service;

import com.example.helloworldfeign.model.HelloMessage;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author billjiang 475572229@qq.com
 * @create 17-8-28
 */
@Component
public class HelloServiceFallbackFactory implements FallbackFactory<HelloService> {
    private final static Logger LOGGER= LoggerFactory.getLogger(HelloServiceFallbackFactory.class);
    @Override
    public HelloService create(Throwable throwable) {
        return new HelloService() {
            @Override
            public HelloMessage hello() {
                //print the error
                LOGGER.error("fallback ,the result is:",throwable);
                HelloMessage helloMessage=new HelloMessage();
                helloMessage.setName("hello");
                helloMessage.setMessage("error occurs");
                return helloMessage;
            }
        };
    }
}

这样会在控制台把具体导致熔断的信息输出,以便跟踪错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,991评论 19 139
  • 1 为什么需要服务发现 简单来说,服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务,而微服务在这个基...
    谦小易阅读 25,150评论 4 93
  • 有关Spring Cloud入门知识和配置方式的博客很多。这里就不仿照他们一篇一个模块的写了。直接上学习和总结的代...
    maven_hz阅读 6,404评论 0 6
  • 在微服务架构中,存在着许许多多的服务单元,若一个服务出现故障,就会因依赖关系形成故障蔓延,最终导致整个系统的瘫痪,...
    WeiminSun阅读 915评论 0 1
  • 想尽一切办法 骗一个需要谎言的自己 我等了好长时间 在失望中看到光明 又在光明中 失去了希望 无奈岁月鸿沟 从此深...
    久疏阅读 539评论 1 6