Hystrix:普通Javaweb结合AOP使用

简介: Hystrix:普通Javaweb结合AOP使用

一、什么是Hystrix



Hystrix是Netflix的一个开源框架,地址如下:https://github.com/Netflix/Hystrix

中文名为“豪猪”,即平时很温顺,在感受到危险的时候,用刺保护自己;在危险过去后,还是一个温顺的肉球。

所以,整个框架的核心业务也就是这2点:

  1. 何时需要保护
  2. 如何保护


二、何时需要保护

  对于一个系统而言,它往往承担着2层角色,服务提供者与服务消费者。对于服务消费者而言最大的痛苦就是如何“明哲保身”,做过网关项目的同学肯定感同身受。

 

 

  上面是一个常见的系统依赖关系,底层的依赖往往很多,通信协议包括socket、HTTP、Dubbo、webservice等等。当通信层发生网络抖动以及所依赖的系统发生业务响应异常时,我们业务本身所提供的服务能力也直接会受到影响。

  这种效果传递下去就很有可能造成雪崩效应,即整个业务联调发生异常,比如业务整体超时,或者订单数据不一致。

  那么核心问题就来了,如何检测业务处于异常状态?

  成功率!成功率直接反映了业务的数据流转状态,是最直接的业务表现。

  当然,也可以根据超时时间做判断,比如Sentinel的实现。其实这里概念上可以做一个转化,用时间做超时控制,超时=失败,这依然是一个成功率的概念。


三、如何保护 

  如同豪猪一样,“刺”就是他的保护工具,所有的攻击都会被刺无情的怼回去。 

在Hystrix的实现中,这就出现了“熔断器(CircuitBreaker)”的概念,即当前的系统是否处于需要保护的状态。

当熔断器处于开启的状态时,所有的请求都不会真正的走之前的业务逻辑,而是直接返回一个约定的信息,即fallBack。通过这种快速失败原则保护我们的系统。

  但是,系统不应该永远处于“有刺”的状态,当危险过后需要恢复正常。

  于是对熔断器的核心操作就是如下几个功能:

  1. 如果成功率过低,就打开熔断器,阻止正常业务
  2. 随着时间的流动,熔断器处于半打开状态,尝试性放入一笔请求

熔断器的原理很简单,如同电力过载保护器。

  • 它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。
  • 熔断器也可以使应用程序能够诊断错误是否已经修正如果已经修正,应用程序会再次尝试调用操作

熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误


熔断器机制

熔断器很好理解, 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务.

断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN).

Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.

  • 熔断器的核心API如下图:

 


四、限流、熔断、隔离、降级

这四个概念是我们谈起微服务会经常谈到的概念,这里我们讨论的是Hystrix的实现方式


限流

  • 这里的限流与guava的RateLimiter的限流差异比较大,一个是为了“保护自我”,一个是“保护下游”
  • 对服务进行限流时,超过的流量将直接fallback,即熔断。而RateLimiter关心的其实是“流量整形”,将不规整流量在一定速度内规整。


熔断

  • 我的应用无法提供服务时,我要对上游请求熔断,避免上游把我压垮。
  • 我的下游依赖成功率过低时,我要对下游请求熔断,避免下游把我拖垮。


降级

  • 降级与熔断紧密相关,熔断后业务如何表现,约定一个快速失败的fallback,即为服务降级。
  • Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.   


隔离

在Hystrix中, 主要通过线程池来实现资源隔离.

通常在使用的时候我们会根据调用的远程服务划分出多个线程池. 例如调用产品服务的Command放入A线程池, 调用账户服务的Command放入B线程池.

这样做的主要优点是运行环境被隔离开了. 这样就算调用服务的代码存在bug或者由于其他原因导致自己所在线程池被耗尽时, 不会对系统的其他服务造成影响.

但是带来的代价就是维护多个线程池会对系统带来额外的性能开销.

如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话, 可以使用Hystrix的信号模式(Semaphores)来隔离资源.

  • 业务之间不可互相影响,不同业务需要有独立的运行空间。
  • 最彻底的,可以采用物理隔离,不同的机器部署。
  • 次之,采用进程隔离,一个机器多个tomcat。
  • 次之,请求隔离。
  • 由于Hystrix框架所属的层级为代码层,所以实现的是请求隔离,线程池或信号量。 


普通Javaweb结合AOP使用Hystrix

maven坐标

        <!-- https://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-metrics-event-stream -->
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-metrics-event-stream</artifactId>
            <version>1.5.12</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica -->
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>1.5.12</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-servo-metrics-publisher</artifactId>
            <version>1.5.12</version>
        </dependency>


web.xml

    <!--HystrixMetricsStreamServlet-->
    <servlet>
        <display-name>HystrixMetricsStreamServlet</display-name>
        <servlet-name>HystrixMetricsStreamServlet</servlet-name>
        <servlet-class>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HystrixMetricsStreamServlet</servlet-name>
        <url-pattern>/hystrix.stream</url-pattern>
    </servlet-mapping>


spring 配置

    <aop:aspectj-autoproxy/>
    <!--用来拦截处理HystrixCommand注解-->
    <bean id="hystrixCommandAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>


service实现类

@HystrixCommand(fallbackMethod="getFallback",commandKey="getUserByName",groupKey="UserGroup",
            threadPoolKey="getUserByNameThread")
    @Override
    public String getUserByName(String name) {
        int i=1/0;
        return "Hello  " + name + "!";
    }
    protected String getFallback(String name) {
        return "faild";
    }


service接口

public String getUserByName(String name);


controller类

@Controller
@RequestMapping("/test")
public class RsaControllerTest {
  private static final Logger log = LoggerFactory.getLogger(RsaControllerTest.class);
  @Autowired
  private UserService userService;
    @RequestMapping(value="hystrix/{name}",method=RequestMethod.GET)
    @ResponseBody
    public String getUserByName (@PathVariable String name) {
        String user = userService.getUserByName(name);
        return "Hello  " + user + "!";
    }
}


测试结果

http://localhost:8080/CloudPayment/test/hystrix/FLY.do

  • 控制台的输出


Hystrix的监控

http://localhost:8080/CloudPayment/hystrix.stream

这种接口数据不便于我们阅读,所以,我们可以借助Hystrix-dashboard转化为图形化的界面

参考链接:https://www.cnblogs.com/kingszelda/p/10312242.html



相关文章
|
Java 数据库
Javaweb之SpringBootWeb案例之AOP案例的详细解析
Javaweb之SpringBootWeb案例之AOP案例的详细解析
110 0
|
Java Spring
Javaweb之SpringBootWeb案例之AOP通知顺序的详细解析
Javaweb之SpringBootWeb案例之AOP通知顺序的详细解析
128 0
|
Java Spring
Javaweb之SpringBootWeb案例之AOP通知类型的详细解析
Javaweb之SpringBootWeb案例之AOP通知类型的详细解析
145 0
|
Java 程序员 数据安全/隐私保护
Javaweb之SpringBootWeb案例之AOP概述及入门的详细解析
Javaweb之SpringBootWeb案例之AOP概述及入门的详细解析
111 0
|
JSON 算法 安全
JavaWeb基础知识-登录效验-spring事务-AOP(二)
2.JWT令牌 全称:JSON Web Token (https:/ljwt.io/) 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。 组成: 第一部分:Header(头),记录令牌类型、签名算法等。例如: {“alg”:“HS256” ,“type” :“JWT”} 第二部分: Payload(有效载荷),携带一些自定义信息、默认信息等。例如:{“id”.“1” ,“username”:“Tom”} 第三部分: Signature(签名),防止Token被篡改、确保安全性。将header、 payload,并加入指定秘钥
|
21天前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
254 0
|
5月前
|
人工智能 监控 Java
面向切面编程(AOP)介绍--这是我见过最易理解的文章
这是我见过的最容易理解的文章,由浅入深介绍AOP面向切面编程,用科普版和专家版分别解说,有概念,有代码,有总结。
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
247 1
|
10月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
1233 1
什么是AOP面向切面编程?怎么简单理解?