您的位置:首页 > 其它

断路器hystrix原理及使用

2017-09-04 15:08 369 查看


原理

在微服务架构中,服务之间形成调用链路,链路中的任何一个服务提供者都可能面临着相应超时、宕机等不可用的情况,在高并发的情况下,这种情况会随着并发量的上升恶化,形成“雪崩效应”,而断路器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;
}
};
}
}


这样会在控制台把具体导致熔断的信息输出,以便跟踪错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hystrix 服务容错