断路器hystrix

2020/09/06 Hystrix

断路器Hystrix

Hystrix是Netflix的一个开源项目,它能够在依赖服务失效的情况下,通过隔离系统依赖服务的方式,防止服务级联失败;同时Hystrix提供失败回滚机制,使系统能够更快地从异常中恢复。

基础应用

spring-cloud-netflix-hystrix对Hystrix进行封装和适配,使Hystrix能够更好地运行于Spring Cloud环境中,为微服务间的调用提供强有力的容错机制。

Hystrix具有如下的功能:

  • 在通过第三方客户端访问(通常是通过网络)依赖服务出现高延迟或者失败时,为系统提供保护和控制。
  • 在复杂的分布式系统中防止级联失败(服务雪崩效应)。
  • 快速失败(Fail fast)同时能快速恢复。
  • 提供失败回滚(Fallback)和优雅的服务降级机制。
  • 提供近实时的监控、报警和运维控制手段。

RestTemplate与Hystrix

可以搭建包含Hystrix依赖的SpringBoot项目。首先添加eureka-client和hystrix的相关依赖,如下所示:

<dependency> <!--eureka-client相关依赖-->
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency> <!--hystrix相关依赖-->
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

在application.yml中为hystrix-service服务配置注册中心地址,代码如下所示:

# application.yml
eureka:
    instance:
        instance-id: ${spring.application.name}:${vcap.application.instance_id:$ {spring.application.instance_id:${random.value}}}
    client:
        service-url:
            default-zone: http://localhost:8761/eureka/
spring:
    application:
        name: hystrix-service
server:
    port: 8876

通过@EnableCircuitBreaker注解开启Hystrix,同时注入一个可以进行负载均衡的RestTemplate,代码如下所示:

@SpringBootApplication
@EnableCircuitBreaker // 开启Hystrix
public class Chapter6HystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(Chapter6HystrixApplication.class, args);
    }
    // 注入可以进行负载均衡的RestTemplate
    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

编写相关的服务,代码如下所示:

@Service
public class InstanceService {
    private static String DEFAULT_SERVICE_ID = "application";
    private static String DEFAULT_HOST = "localhost";
    private static int DEFAULT_PORT = 8080;
    private static Logger logger = LoggerFactory.getLogger(InstanceService.class);
    @Autowired
    RestTemplate restTemplate;
    @HystrixCommand(fallbackMethod = "instanceInfoGetFail")
    public Instance getInstanceByServiceIdWithRestTemplate(String serviceId){

        Instance instance = restTemplate.getForEntity("http://FEIGN-SERVICE/feign-service/instance/{serviceId}", Instance.class, serviceId).getBody();
        return instance;
    }
    private Instance instanceInfoGetFail(String serviceId){
        logger.info("Can not get Instance by serviceId {}", serviceId);
        return new Instance("error", "error", 0);
    }
}

通过@HystrixCommand注解为getInstanceByServiceIdWithRestTemplate方法指定回滚的方法instanceInfoGetFail,该方法返回了全是error的实体类信息。在getInstanceByServiceIdWithRestTemplate方法中通过restTemplate调用feign-service服务的相关的接口,期望返回结果,通过@HystrixCommand注解将该方法纳入到Hystrix的监控中。

编写相关的控制器类,调用getInstanceByServiceIdWithRestTemplate方法,获得结果并返回。代码如下所示:

@RestController
@RequestMapping("/instance")
public class InstanceController {
    private static final Logger logger = LoggerFactory.getLogger(InstanceController.class);
    @Autowired
    InstanceService instanceService;
    @RequestMapping(value = "rest-template/{serviceId}", method = RequestMethod.GET)
    public Instance getInstanceByServiceIdWithRestTemplate(@PathVariable("serviceId") String serviceId){
        logger.info("Get Instance by serviceId {}", serviceId);
        return instanceService.getInstanceByServiceIdWithRestTemplate(serviceId);
    }
}

依次启动eureka-server、feign-service(feign-service为第5章的feign-service项目)以及本服务。访问http://localhost:8876/instance/rest-template/my-application接口。结果如下所示:

{"serviceId":"my-application","host":"localhost","port":8080}

访问成功执行,返回预期结果。关闭feign-service,再次访问http://localhost:/8876/instance/rest-template/my-application接口。结果如下所示:

{"serviceId":"error","host":"error","port":0}

这说明在feign-service服务不可用时,系统执行失败回滚方法,返回“error”结果。

Search

    微信好友

    博士的沙漏

    Table of Contents