当前位置:   article > 正文

【Hystrix】【源码+图解】【一】功能介绍及HelloWorld体验_hystrix源码 流程

hystrix源码 流程

1. Hystrix的功能

Hystrix的功能主要有缓存、熔断(断路器)、隔离(线程池或信号量)、限流(线程池或信号量)、降级处理、请求合并等。

缓存:避免频繁请求资源

熔断:当失败率过高时进行降级处理

隔离:服务隔离,避免A服务的失败影响无关的B服务调用

限流:防止大量的请求冲垮服务,当请求大于阈值时降级处理

降级处理:当服务出现异常时返回友好的处理结果

请求合并:多个单次请求合并成一个请求,减少网络资源等的消耗

下图虽然拙劣,但大概能表达这些功能

在这里插入图片描述

接下来通过一个HelloWorld演示Hystrix的使用,然后再按图索骥逐步分析Hystrix的源码

2. HelloWorld

2.1 引入依赖

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		    <version>2.2.10.RELEASE</version>
		</dependency>
	</dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2. 2开启Hystrix

@SpringBootApplication
@EnableCircuitBreaker // (1)声明式开启Hystrix
public class HystrixApplication {

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

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.3 编写例子

CommandService接口

public interface CommandService {

    public String command(String command, long delay);
}
  • 1
  • 2
  • 3
  • 4

CommandServiceImpl实现类

@Service
public class CommandServiceImpl implements CommandService {

    @Override
    // (2)Hystrix命令声明
    @HystrixCommand(
            // 设置超时时间
            commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")},
            // 超时后的降级处理
            fallbackMethod = "fallbackMethod")
    public String command(String command, long delay) {
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "消息" + command + ",正常: " + delay;
    }
    
    public String fallbackMethod(String command, long delay) {
        return "消息" + command + ",超时了: " + delay;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

HystrixController

@RestController
public class HystrixController {

    @Autowired
    CommandService commandService;
    
    @GetMapping("/commands/{id}")
    public String getCommand(@PathVariable("id")String id) throws ClassNotFoundException {
        // 随机生成时延
        long delay = (long) (Math.random() * 1000);
        return commandService.command(id, delay);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.4 查看结果

代码编写好后启动,在浏览器输入http://localhost:8080/commands/11,结果会有两种,delay小于500ms则正常显示,大于500ms则显示超时。这个简单的例子展示了Hystrix的服务降级功能,那么它是怎么做到的呢?

从例子的代码中我们看到(1)和(2)处用到了Hystrix的代码,那么这两个annotation就成为了研究Hystrix源码的入口。

@EnableCircuitBreaker

@Deprecated
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

@EnableCircuitBreaker中什么代码都没有,它只是用到了@Import(EnableCircuitBreakerImportSelector.class),我们继续分析EnableCircuitBreakerImportSelector

@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector extends SpringFactoryImportSelector<EnableCircuitBreaker> {

	@Override
	protected boolean isEnabled() {
		return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE);
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

从EnableCircuitBreakerImportSelector的代码中我们看到它设置了spring.cloud.circuit.breaker.enabled的值,也就是开启了Hystrix断路器。那么我们就能得出了结论:@EnableCircuitBreaker的功能就是开启Hystrix功能。如果没有这个注解,后面的@HystrixCommand是不起作用的

@HystrixCommand

对于注解一般是使用aspect拦截嵌入功能,而@HystrixCommand也是这样工作的。真正的逻辑是在HystrixCommandAspect类里,我们看下HystrixCommandAspect的源码,为了方便我们把琐碎的代码去掉

    // 拦截@HystrixCommand
	@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
    public void hystrixCommandAnnotationPointcut() {
    }

	// 拦截@HystrixCollapser
    @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
    public void hystrixCollapserAnnotationPointcut() {
    }

    @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
    public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = getMethodFromTarget(joinPoint);
        ......
        // 1、根据注解获取MetaHolderFactory【3】
        MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
        // /2、创建MetaHolder,存储被拦截方法的所有信息,包括方法本身以及@HystrixCommand的信息【4】
        MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
        // /3、创建Hystrix命令【5】
        HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
        ......
        Object result;
        ......
            // /4、执行命令【6】
            if (!metaHolder.isObservable()) {
                result = CommandExecutor.execute(invokable, executionType, metaHolder);
            } else {
                result = executeObservable(invokable, executionType, metaHolder);
            }
        ......
        return result;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

@HystrixCommand的工作流程大致如下

请添加图片描述

那么我们按照这四个步骤继续往下探究Hystrix的源码

未完待续

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/978692
推荐阅读
相关标签
  

闽ICP备14008679号