# fusing-switch **Repository Path**: lichaoever/fusing-switch ## Basic Information - **Project Name**: fusing-switch - **Description**: 服务熔断,可以对依赖的RMI RPC、HTTP等服务加上熔断机制 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-05-11 - **Last Updated**: 2021-05-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 伴随着微服务架构被宣传得如火如荼,一些概念也被推到了我们面前,其实大多数概念以前就有,但很少被提的这么频繁。 在股票市场,熔断这个词大家都不陌生,是指当股指波幅达到某个点后,交易所为控制风险采取的暂停交易措施。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。 这个框架其实就是要解决微服务架构中,服务于服务之间强依赖的一些问题,比如A服务依赖B服务,如果B服务挂了那么A服务会不正常,或者B服务响应很慢,A服务对外响应也很慢,也许只是B服务出现了问题,A服务是正常的,如果不加以处理,整个表现就是A和B都是不可服务的,且会有雪崩的危险。 针对上述情况,比较好的处理结果是,B出现了问题,A可以感知到并且断开依赖B的服务,A按照一种预设的规则进行处理,过一段时间B如果恢复正常了,A可以感知到并且重新连接上依赖B的服务,这种机制就是**服务熔断**机制。 很多人容易把 **服务熔断** 和 **服务降级** 弄混,其实这2者区别还是很大的: **最终表现一样**:最终都是某些服务或功能不可用,提供有损服务 **触发条件不一样**:服务熔断一般是因为下游服务出现了问题而自动触发熔断开关,服务降级可以是人工触发(屏蔽降级)的,也可以是根据自身硬件、软件情况自动主动触发(策略降级) **应用的范围不一样**:服务熔断一般是针对依赖的下游服务,只要存在接口调用就应该存在服务熔断机制,服务降级可以是整个服务降级,也可以是降级服务中的某些功能(比如 在做促销时对商品详情页的评论列表进行降级) 熔断机制的设计思路,把每个服务划分成3种状态: **Closed**:熔断器关闭状态,记录调用失败次数积累,到了阈值则打开熔断开关 **Open**:熔断器打开状态,此时对下游的调用都内部直接返回错误,不走网络,但设计了一个时钟选项,默认的时钟达到了一定时间(这个时间一般设置成平均故障处理时间,也就是MTTR),到了这个时间,进入半熔断状态 **Half-Open**:半熔断状态,允许定量的服务请求,如果在一定的时间范围内成功次数达到阈值,则认为恢复了,关闭熔断器,否则认为还没好,又回到熔断器打开状态 下面上代码,提供了多种方式来给服务于服务之间增加熔断开关(保险丝): # **1 侵入式接入:** **1) 如果依赖的服务是RMI类的接口,比如hassion,dubbo。** FusingSwitchStrategy.call().execute(new AbstractFusingSwitchTarget() { @Override public Object execute() throws Throwable { //要调用的RPC接口 return order.saveOrder("abc123"); } } , //order接口的服务名称,可直接用类名 new AbstractFusingSwitchProvider("com.a.b.c.Order") , //mock execute new AbstractFusingSwitchMock() { @Override public Object executeMock(AbstractFusingSwitchProvider provider) throws Exception { //saveOrder接口的mock实现 //可以throw Exception,可以返回一个对象,可以调用orderMock的saveOrder方法 return orderMock.saveOrder("abc123"); } }); **2)如果依赖的服务是HTTP协议的接口:** FusingSwitchStrategy.call().execute(new AbstractFusingSwitchTarget() { @Override public Object execute() throws Throwable { return sendHTTPRequest("http://orderservice.xxx.com/saveOrder", "abc123") } } , //这块直接使用host作为服务名称 new AbstractFusingSwitchProvider("orderservice.xxx.com") , //mock execute new AbstractFusingSwitchMock() { @Override public Object executeMock(AbstractFusingSwitchProvider provider) throws Exception { //saveOrder接口的mock实现 //可以throw Exception,可以返回一个对象,可以调用orderMock的saveOrder方法 return orderMock.saveOrder("abc123"); } }) # **2 非浸入式接入,使用拦截器(针对RMI协议类有效)** **1) 配置interceptor** **2)配置服务的Mock** 1)新建mock.properties文件 com.package.Order=com.my.OrderMock 2)spring中新增配置 mock.properties ## **推荐使用拦截器的接入方式,无代码侵入,只需要配置拦截器和mock。** # **3 参数配置** 1)新建fusing-switch.properties文件 #close状态下失败次数达到了开启熔断的条件 open_fusing_switch_faild_count=10 #close状态下在指定的时间内失败次数达到了开启熔断的条件 open_fusing_switch_faild_second=120 #open状态持续时间 open_fusing_switch_second=60 #half-open状态下指定的时间内成功次数到达了关闭熔断开关的条件 half_open_fusing_switch_success_second=300 #half-open状态下成功次数达到了关闭熔断开关的条件 half_open_fusing_switch_success_count=5 #出现Exception时,是否使用mock策略 always_use_mock=true 2)spring中新增配置 fusing-switch.properties