SpringCloud断路器-Hystrix-H版

为什么要断路器

微服务之间的调用问题

在微服务中应用通过服务注册和订阅的方式相互依赖。由于应用都在不同的进程中运行,服务之间通过网络远程调用。这样服务之间的调用就可能因为网络原因或者依赖服务自身的问题导致出现调用故障或者延迟的问题。
这个问题同样会导致调用方对外的服务出现延迟或故障,如果此时请求方的调用不断增加,进而影响到整个调用链路上的故障。例如现在有A、B、C三个服务,A调用B,B再调用C,三个服务形成一个调用链。

SpringCloud断路器-Hystrix-H版
调用故障

如上图所示,如果B和C之间因为网络故障导致延迟增长,此时外部还在不断调用。因为网络延迟增加,导致tomcat容器中的线程一直处于占用等待状态,随着时间增加导致tomcat的处理线程大量被占用,进而导致无法向外提供服务,整个服务瘫痪。

如何解决

针对上面的情况,我们应该怎么办呢?一般来说我们有三种解决方案:

熔断模式

这种模式参考的就是我们生活中电路熔断的例子,如果电路中的负载过高,保险丝就会熔断从而防止整个电路被损坏。放在我们的系统中就是如果目标服务调用太慢或者大量超时,此时熔断服务就会被调用,对于后续的请求不再继续调用原先的目标服务,而是通过降级服务快速返回。等原先的目标服务恢复正常时,则恢复对原先服务的调用。

隔离模式

这种模式类似于大型轮渡中的隔离仓一样,如果某个舱内发生故障,立马关闭舱门防止影响到其他正常的仓。对应到程序中就是将不同类型的请求使用线程池来进行资源的隔离,这样每种类型的请求互不影响。如果某种类型的请求线程被消耗殆尽,这样就不会影响到其他服务的线程,这样就防止了故障的进一步扩散。

限流模式

限流模式与上面的两种还不一样,上面两种是在故障发生时的容错处理,而限流则是在请求处理前的预防。限流模式通过提前对各种类型的请求设置QPS阈值,如果QPS达到了设置的阈值则请求立马返回,不再调用后续的资源。

Hystrix

Hystrix主要为我们提供了以下功能:

  • 请求超时降级,线程资源不足或者响应时间过长,方法调用将返回fallback结果。
  • 线程隔离,不同的服务调用可以设置不同的线程池来处理。
  • 自动触发熔断与恢复。
  • 请求缓存和请求合并。

如何使用

快速使用还是很简单的,还是继续使用我们之前的工程,首先在之前的「shop」服务增加Hystrix相关依赖。

<dependency>
     <groupId>org.Springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

第二步使用 「@EnableCircuitBreaker」 开启功能。

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@RibbonClient(name = "user-server",configuration = UserRibbonConfig2.class)
@ComponentScan(basePackages 
"com.yishu.shop",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX,pattern = "com.yishu.shop.ribbon.*")})
@EnableCircuitBreaker
public class ShopApplication {

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

第三步使用 「@HystrixCommand」 注解方法。这里我们编写一个查询订单信息的方法,该方法通过订单号的长度来模拟线程睡眠时间来达到服务超时的效果。

@Component
@Slf4j
public class OrderService {

    @HystrixCommand(fallbackMethod = "getOrderInfoFallback",
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public Object getOrderInfo(String orderNo){
        int length = orderNo.length();
        try {
            TimeUnit.SECONDS.sleep(length);
        } catch (InterruptedException e) {
            log.error("服务出错!",e);
        }
        return "正常返回订单信息:"+orderNo;
    }


    public Object getOrderInfoFallback(String orderNo){
        return "降级返回订单信息:"+orderNo;
    }
}

代码解释:

  • @HystrixCommand 中的fallback代表的是服务降低调用的方法。
  • commandProperties 这个里面可以设置很多属性,例如超时时间,断路器是否打开等等,我们这里设置了服务超时的时间。它有很多属性可以设置,具体请参考Hystrix官网中的描述。
  • getOrderInfoFallback方法。这个就是我们定义的服务降级的方法,fallback中的值就是方法中的值。

最后我们创建一个Controller用来调用OrderService方法。

@RestController
@RequestMapping("order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping()
    public JsonResponse<Object> getOrderInfo(@RequestParam("orderNo")String orderNo){
        Object orderInfo = orderService.getOrderInfo(orderNo);
        return JsonResponse.ok(orderInfo);
    }
}

我们可以尝试调用以下两个URL来查看效果。

  • http://localhost:9000/order?orderNo=1
  • http://localhost:9000/order?orderNo=12345 接口的返回值如下:
{
 "code""2000",
 "msg""请求成功",
 "data""正常返回订单信息:1"
}

{
 "code""2000",
 "msg""请求成功",
 "data""降级返回订单信息:12345"
}

从上面的结果我们可以看出,Hystrix确实生效了。

OpenFeign与Hystrix组合使用

还是我们之前的工程,在之前将OpenFeign的时候我们通过接口+注解的方法完成了对用户信息查询服务的远程调用。现在我们使用OpenFeign与Hystrix组合使用。在使用之前我们需要打开OpenFeign中对Hystrix的支持,该选项默认是关闭的。我们只需要在配置文件中增加如下配置即可:

feign:
  hystrix:
    enabled: true

然后实现UserService接口中fallback实现。

@Component
public class UserServiceFallback implements UserService{

    @Override
    public JsonResponse<UserDto> getUser(Integer id) {
        UserDto userDto = new UserDto();
        userDto.setId(id);
        userDto.setUserName("服务降级调用返回");
        return JsonResponse.ok(userDto);
    }
}

最后我们在 「@FeignClien」 中指定fallback即可。

@FeignClient(name = "user-server",fallback = UserServiceFallback.class)
public interface UserService 
{
    /**
     * 根据用户ID获取用户信息
     * @param id 用户ID
     * @return
     */

    @GetMapping("/user")
    JsonResponse<UserDto> getUser(@RequestParam("id")Integer id);
}

最后启动我们的shop服务,但是不用启动user服务,用来模拟目标服务无法调用的情况。最后访问该接口,接口响应信息如下:

{
 "code""2000",
 "msg""请求成功",
 "data": {
  "id": 1,
  "nickName": null,
  "userName""服务降级调用返回",
  "email": null,
  "phone": null,
  "registerTime": null
 }
}

从结果我们可以看出,最后的不是从user服务返回的,而是我们本地fallback的结果。

总结

上面只是带你快速了解Hystrix的作用和简单使用,Hystrix有很多属性配置,它不仅能通过注解来配置信息,还能通过配置文件来设置这些属性。关于更多Hystrix的信息还请参考官网。

  • 工程代码下载:
git clone -b hystrix https://gitee.com/zengchao_workspace/ys.git


原文始发于微信公众号(一只菜鸟程序员):SpringCloud断路器-Hystrix-H版

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/73070.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!