博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud 核心组件——熔断降级
阅读量:5090 次
发布时间:2019-06-13

本文共 6553 字,大约阅读时间需要 21 分钟。

今天先来说说“服务熔断”和“服务降级”。

服务熔断:在股票市场,熔断这个词大家都不陌生,是指当股指波幅达到某个点后,交易所为控制风险采取的暂停交易措施。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。

服务降级:大家都见过女生旅行吧,大号的旅行箱是必备物,平常走走近处绰绰有余,但一旦出个远门,再大的箱子都白搭了,怎么办呢?常见的情景就是把物品拿出来分分堆,比了又比,最后一些非必需品的就忍痛放下了,等到下次箱子够用了,再带上用一用。而服务降级,就是这么回事,整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。

所以从上述分析来看,两者其实从有些角度看是有一定的类似性的:

1)目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;

2)最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;

3)粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);

4)自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;

而两者的区别也是明显的:

1)触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;

2)管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)

3)实现方式不太一样

参考文章:

 

下面介绍 Hystrix:

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix 是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix 通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。

Hystrix 提供了熔断、隔离、Fallback、Cache、监控等功能。出现错误之后可以 fallback 错误的处理信息,返回一些兜底数据等等。

 

本文的示例承接上一篇文章:

1. Feign 结合 Hystrix 断路器开发

第一步:加入依赖

  
org.springframework.cloud
  
spring-cloud-starter-netflix-hystrix

注意新旧版本问题,所以要以官网为主,不然部分注解会丢失

第二步:启动类里面增加注解 @EnableCircuitBreaker

@SpringBootApplication@EnableFeignClients@EnableCircuitBreakerpublic class OrderServiceApplication {    public static void main(String[] args) {        SpringApplication.run(OrderServiceApplication.class, args);    }    @Bean    @LoadBalanced    public RestTemplate restTemplate() {        return new RestTemplate();    }}

我们也可以使用 SpringCloudApplication 注解,它包含了很多 Spring Cloud 相关的注解

第三步:最外层 api 使用

api 方法上增加 @HystrixCommand(fallbackMethod = "saveOrderFail")。好比异常处理(网络异常,参数或者内部调用问题)

@RestController@RequestMapping("api/v1/order")public class OrderController {    @Autowired    private ProductOrderService productOrderService;    @RequestMapping("save")    @HystrixCommand(fallbackMethod = "saveOrderFail")    public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){        Map
data = new HashMap<>(); data.put("code", 0); data.put("data", productOrderService.save(userId, productId)); return data; } //注意,方法签名一定要要和api方法一致 private Object saveOrderFail(int userId, int productId){
Map
msg = new HashMap<>(); msg.put("code", -1); msg.put("msg", "抢购人数太多,您被挤出来了,稍等重试"); return msg; }}

注意:编写 fallback 方法实现,方法签名一定要和 api 方法签名一致

第四步:进行测试,我们使用一个会出错的请求,它会返回 saveOrderFail 的返回值

 

2. 我们调用服务时,如果服务出错,我们希望可以进行一些处理

 第一步:开启 Feign 支持 Hystrix (注意,一定要开启,旧版本默认支持,新版本默认关闭)

feign:  hystrix:    enabled: true

第二步:FeignClient(name="xxx", fallback=xxx.class ),class 需要继承当前 FeignClient 的类

@FeignClient(name = "product-service", fallback = ProductClientFallback.class)public interface ProductClient {    @GetMapping("/api/v1/product/find")    String findById(@RequestParam(value = "id") int id);}

ProductClientFallback 类

@Componentpublic class ProductClientFallback implements ProductClient {    @Override    public String findById(int id) {        System.out.println("feign 调用product-service findbyid 异常");        return null;    }}

 

3. 进一步完善异常报警通知

我们可以试着加入 Redis 来实现一个异常报警

第一步:加入 Redis 依赖

org.springframework.boot
spring-boot-starter-data-redis

第二步:配置 Redis 链接信息

spring:  redis:    database: 0    host: 127.0.0.1    port: 6379    timeout: 2000

第三步:修改代码

@RestController@RequestMapping("api/v1/order")public class OrderController {    @Autowired    private ProductOrderService productOrderService;    @Autowired    private StringRedisTemplate redisTemplate;    @RequestMapping("save")    @HystrixCommand(fallbackMethod = "saveOrderFail")    public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId, HttpServletRequest request){        Map
data = new HashMap<>(); data.put("code", 0); data.put("data", productOrderService.save(userId, productId)); return data; } //注意,方法签名一定要要和api方法一致 private Object saveOrderFail(int userId, int productId, HttpServletRequest request){ //监控报警 String saveOrderKye = "save-order"; String sendValue = redisTemplate.opsForValue().get(saveOrderKye); final String ip = request.getRemoteAddr(); new Thread( ()->{ if (StringUtils.isBlank(sendValue)) { System.out.println("紧急短信,用户下单失败,请离开查找原因,ip地址是="+ip); //发送一个http请求,调用短信服务 TODO redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS); }else{ System.out.println("已经发送过短信,20秒内不重复发送"); } }).start(); Map
msg = new HashMap<>(); msg.put("code", -1); msg.put("msg", "抢购人数太多,您被挤出来了,稍等重试"); return msg; }}

 

4. Hystrix 降级策略和调整

1)查看默认讲解策略 HystrixCommandProperties

这个文件里可以看到所有默认的策略

2)execution.isolation.strategy 隔离策略

Hystrix 有两种隔离策略:THREAD 线程池隔离 (默认)、SEMAPHORE 信号量。信号量适用于接口并发量高的情况,如每秒数千次调用的情况,导致的线程开销过高,通常只适用于非网络调用,执行速度快

3)execution.isolation.thread.timeoutInMilliseconds 超时时间

Hystrix 默认超时时间为1000毫秒

4)execution.timeout.enabled 是否开启超时限制 (一定不要禁用)

Hystrix 默认是开启超时限制的

5)execution.isolation.semaphore.maxConcurrentRequests 隔离策略为 信号量的时候,如果达到最大并发数时,后续请求会被拒绝,默认是10

#把hystrix超时时间禁用#hystrix:#  command:#    default:#      execution:#        timeout:#          enabled: false#execution.isolation.thread.timeoutInMilliseconds=4000#设置超时时间hystrix:  command:    default:      execution:        isolation:          thread:            timeoutInMilliseconds: 4000

官方文档:

5. 断路器 Dashboard 监控仪表盘

生产环境几乎不用,只要做好异常告警就可以

第一步:加入依赖

  
org.springframework.cloud
  
spring-cloud-starter-netflix-hystrix-dashboard
  
org.springframework.boot
  
spring-boot-starter-actuator

第二步:启动类增加注解 @EnableHystrixDashboard

第三步:配置文件增加 endpoint

#暴露全部的监控信息management:  endpoints:    web:      exposure:        include: "*"

第四步:访问入口

1)访问:

2)Hystrix Dashboard 输入:

参考资料:

 

 

补充: 如果从 Maven 中心仓库下载太慢,可是修改 Maven 仓库地址,使用其他 Maven 仓库。为了使用阿里云的仓库,我们在 pom.xml 中修改

  
    
nexus-aliyun
    
Nexus aliyun
    
default
    
http://maven.aliyun.com/nexus/content/groups/public
    
      
false
    
    
      
true
    
  

 

转载于:https://www.cnblogs.com/jwen1994/p/11432842.html

你可能感兴趣的文章
201521123024 《java程序设计》 第12周学习总结
查看>>
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>
IdentityServer4-用EF配置Client(一)
查看>>
WPF中实现多选ComboBox控件
查看>>
读构建之法第四章第十七章有感
查看>>
Windows Phone开发(4):框架和页 转:http://blog.csdn.net/tcjiaan/article/details/7263146
查看>>
Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)【转】
查看>>
python asyncio 异步实现mongodb数据转xls文件
查看>>
TestNG入门
查看>>
【ul开发攻略】HTML5/CSS3菜单代码 阴影+发光+圆角
查看>>
IOS-图片操作集合
查看>>
IO—》Properties类&序列化流与反序列化流
查看>>
测试计划
查看>>
Mysql与Oracle 的对比
查看>>
jquery实现限制textarea输入字数
查看>>
Codeforces 719B Anatoly and Cockroaches
查看>>
jenkins常用插件汇总
查看>>
c# 泛型+反射
查看>>
第九章 前后查找
查看>>
Python学习资料
查看>>