转载请注明出处 http://www.paraller.com

代码机制:熔断 & Fallback & 资源隔离

熔断

概念:

在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,最终导致自身服务的瘫痪。

举个例子,在一个电商网站中,我们可能会将系统拆分成,用户、订单、库存、积分、评论等一系列的服务单元。用户创建一个订单的时候,在调用订单服务创建订单的时候,会向库存服务来请求出货(判断是否有足够库存来出货)。此时若库存服务因网络原因无法被访问到,导致创建订单服务的线程进入等待库存申请服务的响应,在漫长的等待之后用户会因为请求库存失败而得到创建订单失败的结果。如果在高并发情况之下,因这些等待线程在等待库存服务的响应而未能释放,使得后续到来的创建订单请求被阻塞,最终导致订单服务也不可用。

在微服务架构中,存在着那么多的服务单元,若一个单元出现故障,就会因依赖关系形成故障蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构就更加的不稳定。为了解决这样的问题,因此产生了断路器模式。

断路器模式源于Martin Fowler的Circuit Breaker一文。“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。

在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

Netflix Hystrix:

在Spring Cloud中使用了Hystrix 来实现断路器的功能。Hystrix是Netflix开源的微服务框架套件之一,该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。

Feign使用Hystrix:
我们不需要在Feigh工程中引入Hystix,Feign中已经依赖了Hystrix,但是不推荐这样做,太隐秘了 , 不好自定义,维护成本也高

application.yml:

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: false
      circuitBreaker:
        enabled: true
        requestVolumeThreshold: 3

Fallback

相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.

程序的入口添加注释

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
@EnableHystrixDashboard
@RibbonClient(name = "yea-ribbon", configuration = YeaRibbonConfiguration.class)
@ComponentScan(basePackages = { "cn.yeamoney.**" })
public class Application {

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

}

类调用样例

@FeignClient(value = "ticket-service", configuration = YeaFeignConfiguration.class, fallback = TicketClientHystrix.class)
interface TicketClient {

    @RequestMapping(method = RequestMethod.POST, value = "/create")
    Message<String> create(
            @RequestParam(value = "Type") Integer Type, 
            @RequestParam(value = "amount") String amount,
            @RequestParam(value = "userId") String userId, 
            @RequestParam(value = "mobile") String mobile,
            @RequestParam(value = "status") Integer status, 
            @RequestParam(value = "belong") Integer belong,
            @RequestParam(value = "useProfit")String useProfit,
            @RequestParam(value = "useCounter")String useCounter);

}

/**
 * @author zhidaliao
 * 
 *         错误处理
 */
@Component
class TicketClientHystrix implements TicketClient {

    @Override
    public Message<String> create(Integer Type, String amount, String userId, String mobile, Integer status,
            Integer belong, String useProfit, String useCounter) {
        // TODO 自动生成的方法存根
        return null;
    }

    
}

资源隔离 -- 待完善。。。。

介绍
在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.
例如调用产品服务的Command放入A线程池, 调用账户服务的Command放入B线程池. 这样做的主要优点是运行环境被隔离开了. 这样就算调用服务的代码存在bug或者由于其他原因导致自己所在线程池被耗尽时, 不会对系统的其他服务造成影响.
但是带来的代价就是维护多个线程池会对系统带来额外的性能开销. 如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话, 可以使用Hystrix的信号模式(Semaphores)来隔离资源.

自定义 hystrix command -- 待完善。。。

关键字:@HystrixCommand(ignoreExceptions = .class) 、 javanica 、 HystrixCommand 、Feign中自定义 Hystrix的groupKey commandKey threadPoolKey

看板及监控 - Hystrix Dashboard & monitor

monitor

想要程序自带监控的功能,可以在Springboot中加上

@EnableHystrixDashboard

程序正常启动之后
访问http://localhost:8081/hystrix.stream 即可查看数据流
访问 http://localhost:8081/hystrix 可以查看UI界面

Dashboard

1、功能比较全面的镜像,支持turbine , 分布式监控。 kennedyoliveira/hystrix-dashboard:kennedyoliveira/standalone-hystrix-dashboard , 可以在输入框中输入 Eureka的地址 http://localhost:9761/eureka/apps

2、浏览器地址: http://localhost:7979/hystrix-dashboard/

3、在输入框中输入要监控的网址,例如: http://localhost:8081/hystrix.stream,即可查看情况

image


image


image

Turbine

在复杂的分布式系统中,相同服务的节点经常需要部署上百甚至上千个,很多时候,运维人员希望能够把相同服务的节点状态以一个整体集群的形式展现出来,这样可以更好的把握整个系统的状态。 为此,Netflix提供了一个开源项目(Turbine)来提供把多个hystrix.stream的内容聚合为一个数据源供Dashboard展示。

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>

application.yml

turbine: 
  appConfig: yea-service
  aggregator: 
    clusterConfig: default
    clusterNameExpression: new String("default")
  • turbine.appConfig :配置Eureka中的serviceId列表,表明监控哪些服务
  • turbine.aggregator.clusterConfig :指定聚合哪些集群,多个使用”,”分割,默认为default。可使用http://.../turbine.stream?clu...{clusterConfig之一}访问
  • turbine.clusterNameExpression :

    • clusterNameExpression指定集群名称,默认表达式appName;此时:turbine.aggregator.clusterConfig需要配置想要监控的应用名称;
    • 当clusterNameExpression: default时,turbine.aggregator.clusterConfig可以不写,因为默认就是default;
    • 当clusterNameExpression: metadata[‘cluster’]时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster: ABC,则需要配置,同时turbine.aggregator.clusterConfig: ABC

在入口程序中添加注释

@EnableTurbine

测试

http://localhost:8001/turbine.stream

PS:在添加了 hystrix的程序里面添加turbine ,会导致 /hystrix.stream 链接无效。
建议新建一个项目,然后添加 turbine的功能,不要在微服务中添加。

其他知识点

Hystrix Timeouts And Ribbon Clients

当Hystrix和ribbon配合使用的时候,如果希望 Hystrix的超时时间大于ribbon配置的超时时间,你要考虑到重试次数,例如 Ribbon的超时时间是一秒,重试三次,那你的 Hystrix超时时间必须大于三秒。

引入 hystrix需要的Jar包

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

参考链接


paraller
207 声望12 粉丝