SpringCloud学习Day03

注:本教程均是参考"程序猿DD"大佬的SpringCloud教程:http://blog.didispace.com/spring-cloud-learning/实践结合自己的理解和总结编写

服务降级、线程隔离
相较于传统架构,微服务架构,由于每个服务在不同的进程中运行,服务间通过http协议进行调用,如果依赖服务出现故障或者阻塞将会导致对外的服务延迟,如果此时请求数量继续增加,可能会出现因等待故障而形成请求积压、线程资源无法释放,导致服务瘫痪。Spring Cloud Hystrix实现了线程隔离、断路器、服务降级、服务熔断等功能,给我们的微服务架构添加了可靠性的保障。

服务降级机制
1.添加pom.xml

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

2.在启动类上添加注解@EnableCircuitBreaker

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class EurekaRibbonHystrixConsumerApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaRibbonHystrixConsumerApplication.class).web(true).run(args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

其实启动类上的三个注解等同于@SpringCloudApplication注解
3.改造Controller

@RestController
public class DcController {

    @Resource
    private ConsumerService consumerService;

    @GetMapping("/consumer")
    public String dc() {
        return consumerService.consumer();
    }
}

4.添加ConsumerService

@Service
public class ConsumerService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "fallback")
    public String consumer() {
        return restTemplate.getForObject("http://eureka-client/dc", String.class);
    }

    public String fallback() {
        return "fallback";
    }
}

5.对eureka-client对应的服务方法添加Thread.sleep(5000);启动服务进行测试,然后访问GET http://ip:port/consumer,此时返回结果为fallback。这是由于服务消费方出发了请求超时异常,服务消费方通过HystrixCommand注解指定的降级逻辑执行。这样便可以对自身服务提供了保护。

线程隔离:
我对线程池隔离的理解:
比如a服务的接口a-interface需要调用b,c服务b-interface,c-interface实现自身的业务;在没有做线程隔离的情况下,每次调用a-interface接口a服务的tomcat都会创建一个线程执去调用b-interface,c-interface,如果调用b-interface或者c-interface阻塞了(或者接口延迟高),这个时候又有大量的a-interface调用,,那么容器的线程数量会持续增加导致CPU耗尽导致整个服务不可用,Hystrix通过命令模式将每个类型的请求封装为一个command请求,b-interface封装为b-interface-command,c-interface封装为b-interface-command,每个类型的command对应一个线程池,创建好的线程池是被放入到ConcurrentHashMap中。执行依赖代码的线程与请求线程分离,请求线程可以自由控制离开时间,即异步。Hystrix是结合RxJava来实现的异步编程。通过设置线程池大小来控制并发访问量,当线程饱和的时候可以拒绝服务,防止依赖问题扩散。
通过对依赖服务的线程池隔离实现,有以下优势:
[1]:应用程序会被完全保护起来,即使依赖的一个服务的线程池满了,也不会影响到应用程序的其他部分。
[2]:我们给应用程序引入一个新的风险较低的客户端lib的时候,如果发生问题,也是在本lib中,并不会影响到其他内容,因此我们可以大胆的引入新lib库。
[3]:当依赖的一个失败的服务恢复正常时,应用程序会立即恢复正常的性能。
[4]:如果我们的应用程序一些参数配置错误了,线程池的运行状况将会很快显示出来,比如延迟、超时、拒绝等。同时可以通过动态属性实时执行来处理纠正错误的参数配置。
[5]:如果服务的性能有变化,从而需要调整,比如增加或者减少超时时间,更改重试次数,就可以通过线程池指标动态属性修改,而且不会影响到其他调用请求。
[6]:除了隔离优势外,hystrix拥有专门的线程池可提供内置的并发功能,使得可以在同步调用之上构建异步的外观模式,这样就可以很方便的做异步编程(Hystrix引入了Rxjava异步框架)。
线程隔离的缺点:
[1]:线程池的主要缺点就是它增加了计算的开销,每个业务请求(被包装成命令)在执行的时候,会涉及到请求排队,调度和上下文切换。不过Netflix公司内部认为线程隔离开销足够小,不会产生重大的成本或性能的影响。
The Netflix API processes 10+ billion Hystrix Command executions per day using thread isolation. Each API instance has 40+ thread-pools with 5–20 threads in each (most are set to 10).
Netflix API每天使用线程隔离处理10亿次Hystrix Command执行。 每个API实例都有40多个线程池,每个线程池中有5-20个线程(大多数设置为10个)。
信号量机制
信号量的资源隔离只是起到一个开关的作用,比如,服务 A 的信号量大小为 10,那么就是说它同时只允许有 10 个 tomcat 线程来访问服务 A,其它的请求都会被拒绝,从而达到资源隔离和限流保护的作用。
适用场景:
线程池技术,适合绝大多数场景,比如说我们对依赖服务的网络请求的调用和访问、需要对调用的 timeout 进行控制(捕捉 timeout 超时异常)。
信号量技术,适合说你的访问不是对外部依赖的访问,而是对内部的一些比较复杂的业务逻辑的访问,并且系统内部的代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流就可以了,因为不需要去捕获 timeout 类似的问题。

参考:https://www.jianshu.com/p/fcbc5de24153

代码:https://github.com/SpringStudent/study-spring-cloud

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值