SpringCloud-断路器(Hystrix)
1.什么是服务雪崩
在上面的图中:tomcat都有一个默认的最大线程数量,如果当客户端请求量比较高的时候,则会阻塞!例如 tomcat当前的最大线程数是50条,此时如果有51条 则tomcat则不会有空余的线程处理新的请求!客户端请求订单服务,在订单服务项目中,提供了两个接口,接口一又需要调用会员服务的接口,如果在网络不可达的情况下,订单服务调用会员服务接口的时候 超时!此时订单服务 处于等待状态,如果前50个请求都是通过访问订单服务接口一,那么前50个请求都将处于等待状态,第51个请求订单服务接口二的时候,此时已经没有多的线程可以处理该请求,所有的服务都将不可用、可以理解成服务雪崩!
分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而Hystrix的出现,给我们提供了另一种选择.
2.出现服务雪崩的原因:
- 可能是某个服务机器宕机
- 高并发导致服务器请求处理不过来
- 网络不可达,超时
- 程序员bug导致等
3.解决或缓解服务雪崩的方案
一般情况对于服务依赖的保护主要有3中解决方案:
(1)熔断模式:我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
(2)隔离模式:例如可以对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。这种模式使用场景非常多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者公司最近推广的多中心。
(3)限流模式:上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS(吞吐量)阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。
4.什么是Hystrix
Hystrix 是一个帮助解决分布式系统交互时超时处理和容错的类库, 它同样拥有保护系统的能力.
5.为什么需要 Hystrix
在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC)。为了保证其高可用,单个服务又必须集群部署。由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪崩”。为了解决这个问题,就出现断路器模型,Springcloud Hystrix 解决RPC 远程调用超时或者服务报错等导致的服务雪崩问题 Hystrix提供服务超时降级,熔断机制,服务隔离
6.Hystrix服务调用超时降级demo:
使用feign远程调用member-server服务的时候,如果member-sever出现服务超时,服务降级,访问本地接口
启动feign-server 和eureka-server member-server 服务
feign-server controller 部分代码
package com.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.service.MemberFeign; @RestController public class FeginController { @Autowired private MemberFeign memberFeign; @RequestMapping("/getToMemberAll") public String getToMemberAll() { return memberFeign.getToMemberAll(); } }
feign-server service 代码
package com.service;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "service-member") // 该注解调用的是eureka注册服务中名字是 service-member 的服务
public interface MemberFeign {
@RequestMapping("/getFeiginMemberMsg") // service-member 提供的接口名字 ,底层也是使用httpclient方法调用
public String getToMemberAll();
}
member-server controller 代码
package com.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ReqController {
@Value("${server.port}")
public int port;
@RequestMapping("/getFeiginMemberMsg")
public String getFeiginMemberMsg() throws InterruptedException {
String str = "使用feign调用" + "端口" + port;
return str;
}
}
浏览器地址:http://127.0.0.1:8765/getToMemberAll
在member-server中修改 controller 代码 延迟5秒钟
package com.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ReqController {
@Value("${server.port}")
public int port;
@RequestMapping("/getFeiginMemberMsg")
public String getFeiginMemberMsg() throws InterruptedException {
Thread.sleep(5000);
String str = "使用feign调用" + "端口" + port;
return str;
}
}
如果服务超时,导致服务不可用,可以使用Hystrix降级处理
yml配置文件增加Hystrix配置:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8765
tomcat:
max-threads: 200 //配置tomcat最大的线程数
spring:
application:
name: service-order-feign
feign:
hystrix:
enabled: true //开启hystrix功能
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 4000 //服务延迟时间
创建一个异常返回类 MemberFeignService 该类实现了 MemberFeign 接口
@FeignClient(value = "service-member",fallback = MemberFeignService.class)
public interface MemberFeign {
@RequestMapping("/getFeiginMemberMsg")
public List<String> getOrderByUserList();
}
@Component
public class MemberFeignService implements MemberFeign {
public List<String> getOrderByUserList() {
List<String> listUser = new ArrayList<String>();
listUser.add("time out");
return listUser;
}
如果当程序正常执行的时候,调用的是接口方法,如果程序出现异常 则调用的 memberFeignService的方法,分别将member-service的延迟时间调整到大于4秒或者小于4秒 最后的结果不一样,这样就实现了服务的降级
当超时时间大于yml配置时间的时候 结果:
服务和服务调用时候 出现异常,可以通过hystrix对服务降级,防止服务雪崩 在feign调用的时候添加 fallback = MemberFeignService.class。服务调用出现异常则直接调用 fallback的实现方法,而不需要在去调用远程方法,释放服务资源