SpringCloud Alibaba微服务实战五 - 限流熔断

简介: SpringCloud Alibaba微服务实战五 - 限流熔断

导读:本篇作为SpringCloud Alibaba微服务实战系列的第五篇,主要内容是使用Sentinel给微服务加上限流熔断功能,防止异常情况拖垮应用服务。系列文章,欢迎持续关注。


简介


Sentinel是面向分布式服务框架的轻量级流量控制框架,主要以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来维护系统的稳定性。在SpringCloud体系中,sentinel主要是为了替换原Hystrix的功能,与Hystrix相比,sentinel的隔离级别更加精细,提供的Dashboard可以在线更改限流熔断规则,而且使用也越加方便。要了解更多详细信息请移步至Sentinel官网。


基础准备


要使用Sentinel提供的限流熔断能力,需要先做如下准备:

  • 安装Sentinel 这部分内容我已经在第一期SpringCloud Alibaba微服务实战一 - 基础环境准备中提过,大家可以翻阅查看。
  • 引入Sentinel 在需要配置限流熔断服务的POM文件中引入Sentinel组件
<!--Sentinel-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  • 自定义资源@SentinelResource我们只需要在相关方法上加上@SentinelResource注解,让其可以成为sentinel识别的资源即可。如:
@GetMapping("/account/getByCode/{accountCode}")
@SentinelResource(value = "getByCode")
public ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode){
  log.info("get account detail,accountCode is :{}",accountCode);
  AccountDTO accountDTO = accountService.selectByCode(accountCode);
  return ResultData.success(accountDTO);
}
  • 在配置文件中添加sentinel的服务端地址
server:
  port:8010
spring:
  application:
    name:account-service
  cloud:
    nacos:
      discovery:
        server-addr:192.168.0.107:8848/
    sentinel:
      transport:
      # sentinel服务端地址
        dashboard:192.168.0.107:8858
      # 取消延迟加载
      eager:true

经过以上几步我们准备好了使用Sentinel的基础环境,接下来我们看看限流熔断的具体配置。


限流


概念说明

生产者accout-service是一个核心服务,我们通过压测得出服务的最大负载能力为60。如果某个时间account-service的请求数飙升达到了600,那服务肯定就直接gg了。所以为了保护我们的accout-service,我们会给它配置一个限流规则,如果每秒钟有超过60的请求那不好意思我直接丢掉不处理了,然后丢给消费者一个异常,想拖垮我,哼,没门!。

总而言之,限流是通过限制调用方对自己的调用,起到保护自己系统的效果。


限流配置

理想是丰满的,现实是骨感的。由于本人对Jmeter之类的压测工具不是很精通所以为了方便测试,我们就将accout-service的QPS单机阈值设置成5,如果每秒QPS超过5,直接丢弃。

这里的资源名就是我们使用@SentinelResource注解自定义的资源。

打开浏览器,快速刷新浏览器,当每秒请求数超过5时会看到如下错误:


在后端服务日志中你会看到如下的错误日志:

2019-12-10 14:22:31,948 ERROR [dispatcherServlet]:175 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause
com.alibaba.csp.sentinel.slots.block.flow.FlowException: null

不要慌,这说明我们的目的达到了,限流成功!


自定义异常

我们可以通过@SentinelResource中添加blockHandler参数,给其添加自定义异常方法。如:

@GetMapping("/account/getByCode/{accountCode}")
@SentinelResource(value = "getByCode",blockHandler = "handleException")
public ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode){
  log.info("get account detail,accountCode is :{}",accountCode);
  AccountDTO accountDTO = accountService.selectByCode(accountCode);
  return ResultData.success(accountDTO);
}
/**
 * 自定义异常策略
 * 返回值和参数要跟目标函数一样,参数可以追加BlockException
 */
public ResultData<AccountDTO> handleException(String accountCode,BlockException exception){
  log.info("flow exception{}",exception.getClass().getCanonicalName());
  return ResultData.fail(900,"达到阈值了,不要再访问了!");
}

注意,自定义的异常方法的参数和返回值要跟目标方法一样,参数可以追加BlockException

效果如下:

比之前的那个错误页优雅多了有木有!


持久化配置

由于Sentinel的配置默认是放在内存中的,每当应用重启或者sentinel重启都会丢失数据,我们这里使用Nacos作为配置中心持久化限流配置。

  • 修改pom文件,引入sentinel-datasource-nacos组件
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  • 修改application.yml,配置sentinel的数据源
spring:
  cloud:
    sentinel:
      datasource:
        ds:
          nacos:
            server-addr:10.0.10.48:8848
            data-id:${spring.application.name}-sentinel
            group-id:DEFAULT_GROUP
            rule-type:flow
  • 在nacos中建立限流配置account-service-sentinel(配置格式设置成json)
[
    {
        "resource": "getByCode",
        "limitApp": "default",
        "grade": 1,
        "count": 3,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

可以看到上面配置规则是一个数组类型,数组中的每个对象是针对每一个保护资源的配置对象,每个对象中的属性解释如下:

resource:资源名,即限流规则的作用对象

limitApp:流控针对的调用来源,若为 default 则不区分调用来源

grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制

count:限流阈值

strategy:调用关系限流策略

controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)

clusterMode:是否为集群模式

  • 进入sentinel查看dashboard,发现sentinel自动获取nacos的配置
  • 频繁刷新浏览器调用接口,验证接口是否正常限流

熔断


概念说明

消费者order-service需要先调用product-service获取具体的product,然后再处理其他的业务逻辑。但是这个product-service接口不是很稳定,经常抛出异常;或者是响应缓慢,导致order-service的响应变慢;如果置之不理,order-service可能会被product-service拖垮。这时候为了保护order-service,我们需要对product-service接口进行熔断。

image.png

一言以蔽之:熔断是通过限制自己对外部系统的调用, 起到节约响应时间、维护链路稳定的作用。


熔断配置

Sentinel中的熔断降级有三个降级策略:

  • RT(平均响应时间):当资源的平均响应时间超过阈值之后,资源进入准降级状态。接下来如果持续进入 5 个请求,它们的 RT 都持续超过这个阈值,那么在接下的时间窗口之内,对这个方法的调用都会自动抛出 DegradeException 异常。在下一个时间窗口到来时, 会接着再放入5个请求, 再重复上面的判断.
  • 异常比例 当资源的每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下的时间窗口之内,对这个方法的调用都会自动地抛出DegradeException异常。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 当资源近 1 分钟的异常数目超过阈值之后会进行熔断。

首先我们对原接口进行改造,让其直接抛出Runtimeexception

@GetMapping("/product/getByCode/{productCode}")
@SentinelResource(value = "/product/getByCode",fallback = "fallbackHandler")
public ResultData<ProductDTO> getByCode(@PathVariable String productCode){
  log.info("get product detail,productCode is :{}",productCode);
  ProductDTO productDTO = productService.selectByCode(productCode);
  thrownew RuntimeException("error");
//        return ResultData.success(productDTO);
}

这里我们将product-service设置如下的熔断规则:

如果/product/getByCode的异常率超过50%,那么接下来2秒内直接触发熔断降级,默认情况会抛出DegradeException异常,如:

2019-12-10 19:35:53,764 ERROR [dispatcherServlet]:175 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause
com.alibaba.csp.sentinel.slots.block.degrade.DegradeException: null


自定义异常

自定义熔断异常跟限流异常类似,我们使用fallback属性指定自定义异常的方法,如:

@SentinelResource(value = "/product/getByCode",fallback = "fallbackHandler")
public ResultData<ProductDTO> getByCode(@PathVariable String productCode){
 ...
}
/**
 * 自定义熔断异常
 * 返回值和参数要跟目标函数一样
 */
public ResultData<ProductDTO> fallbackHandler(String productCode){
  return ResultData.fail(800,"服务被熔断了,不要调用!");
}

注意,自定义的异常方法的参数和返回值要跟目标方法一样

效果如下:

持久化配置

  • 引入sentinel-datasource-nacos组件,跟限流一样配置即可
  • 修改application.yml,配置sentinel的数据源
spring:
  cloud:
    sentinel:
      datasource:
        ds:
          nacos:
            server-addr:192.168.0.106:8848
            data-id:${spring.application.name}-sentinel-degrade
            group-id:DEFAULT_GROUP
            rule-type:degrade
  • 在nacos中建立配置文件product-service-sentinel-degrade,做如下配置
[
    {
    "resource": "/product/getByCode",
    "count": 0.5,
    "grade": 1,
    "passCount": 0,
    "timeWindow": 2
  }
]

可以看到上面配置规则是一个数组类型,数组中的每个对象是针对每一个保护资源的配置对象,每个对象中的属性解释如下:

resource:资源名,即降级规则的作用对象

count:阈值

grade:降级模式 0:RT 1:异常比例 2:异常数

timeWindow:时间窗口(单位秒)

  • 进入sentinel查看dashboard,发现sentinel自动获取nacos的配置


血与泪


大家在使用sentinel过程中如果出现Failed to fetch metric from的错误,具体表现如下:

Failed to fetch metric from <http://192.168.136.1:8719/metric?startTime=1563865044000&endTime=1563865050000&refetch=false>
 (ConnectionException: Connection refused: no further information)

这个时候你需要去检查下sentinel控制台的服务列表,确认是否跟你ip一致。(我之前是装过虚拟机,sentinel一直抓取的是我虚拟的ip,不知道为什么。。。)

如果发现监听的地址不对的话,可以在sentinel客户端配置中加入客户端ip配置

spring:
  cloud:
    sentinel:
      transport:
        client-ip:192.168.0.108


至此我们已经给我们的微服务加上了限流熔断保护,再也不用担心异常流量的冲击,下游系统不稳定导致自身服务不可用了。那么本期的“SpringCloud Alibaba微服务实战五 - 限流熔断”篇也就该结束啦,咱们下期有缘再见!

目录
相关文章
|
26天前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
138 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
22天前
|
存储 JavaScript 开发工具
基于HarmonyOS 5.0(NEXT)与SpringCloud架构的跨平台应用开发与服务集成研究【实战】
本次的.HarmonyOS Next ,ArkTS语言,HarmonyOS的元服务和DevEco Studio 开发工具,为开发者提供了构建现代化、轻量化、高性能应用的便捷方式。这些技术和工具将帮助开发者更好地适应未来的智能设备和服务提供方式。
56 8
基于HarmonyOS 5.0(NEXT)与SpringCloud架构的跨平台应用开发与服务集成研究【实战】
|
10天前
|
搜索推荐 NoSQL Java
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
58 16
|
3天前
|
人工智能 安全 Java
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
|
27天前
|
存储 SpringCloudAlibaba Java
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论。
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
|
13天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
14天前
|
人工智能 自然语言处理 Java
Spring Cloud Alibaba AI 入门与实践
本文将介绍 Spring Cloud Alibaba AI 的基本概念、主要特性和功能,并演示如何完成一个在线聊天和在线画图的 AI 应用。
192 7
|
18天前
|
Java 关系型数据库 数据库
微服务SpringCloud分布式事务之Seata
SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程
42 1
|
2月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
167 6
|
2月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
64 1