微服务架构➖SpringCloud➖Sentinel

微服务架构➖SpringCloud➖Sentinel

关于作者

  • 作者介绍

🍓 博客主页:作者主页

🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉 🏆、阿里云专家博主51CTO专家博主

🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨‍💻


Spring Cloud Alibaba Sentinel

服务雪崩效应以及服务容错

由于tomcat等服务器支持的最大线程数有限,如果一个服务出现了问题,调用这个服务的服务器就会出现线程阻塞的情况,此时如果有大量请求进入,就会导致服务瘫痪,这个服务器上的其他接口也不能调用,继而导致其他服务也会阻塞,瘫痪。 这种传播就是服务雪崩效应。我们无法完全杜绝雪崩源头的发生,只有做好足够的容错,保证在一个服务发生问题,不会影响到其它服务的正常运行。也就是"雪落而不雪崩"。 服务容错:常见的容错思路有隔离、超时、限流、熔断、降级这几种。 降级:类似于try/catch,在服务接口级别的try/catch 容错组件有:Hystrix,Resilience4J,Sentinel。

1.Sentinel初识

Sentinel (分布式系统的流量防卫兵)是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。

Sentinel具有以下特征:

  • 丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。

  • 完备的实时监控:Sentinel提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。

  • 广泛的开源生态:Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud、Dubbo.gRPC的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。

  • 完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

sentinel分为两个部分:

  • 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo / Spring Cloud等框架也有较好的支持。
  • 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat 等应用容器。

2. Sentinel的使用

2.1 Sentinel的集成

  • 在pom.xml中加入下面依赖(给需要流量控制的微服务模块添加)
xml 复制代码
<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  • 下载控制台jar包,sentinel-dashboard-1.7.0.jar

  • 修改配置(每个集成了Sentinel的微服务模块都要加):

yaml 复制代码
spring:
  cloud:
    sentinel:
      transport:
        port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: localhost:8080 # 指定控制台服务的地址
  • 运行命令启动jar包,sentinel-dashboard-1.7.0.jar
shell 复制代码
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.0.jar
  • 访问localhost:8080 进入控制台 ( 默认用户名密码是sentinel/sentinel ) 控制台界面如下图所示

注:需要微服务访问一次,才能刷新加载出微服务的资源信息。

2.2 Sentinel主要功能

流量控制:将请求排成队列形状处理。

熔断降级:当要调用的服务的响应时间变长或者异常比例升高的时候,减少该调用的并发线程数量,快速失败,以限制其对资源的占用。(hystrix利用线程池隔离的方式进行限制,线程池隔离:对每个服务调用接口划分一块线程池,调用某服务只能使用对应线程池里的线程,因此达到隔离效果不影响统一服务器上的其他接口)

系统负载保护:集群环境下,当cpu,内存快占满时,把请求发到其他机器上去。

2.3 Sentinel规则

2.3.1 流控规则

对某一资源设置访问频率限制

阈值类型 :频率指标有QPS(每秒请求次数),线程数(并发线程个数) 单机阈值:对上述频率定量规则

流控模式:直接:对资源的直接限制。 关联:当某一资源达到上述设定的限制时,另一资源会被限流。 链路:假设有一个服务A,会调用另一个资源B(可以是一个接口,也可以是一个方法,用@SentinelResource注解可以设置该资源的名字),当b满足上述访问频率时,会对a进行限流。

流控效果:快速失败:当一个资源被流控时,再次访问该资源时直接出异常界面。 Warm up:预热,逐渐放开频率限制,阈值逐渐增长。 排队等待:处理不过来的请求会放到队列中等待被处理。

2.3.2 降级规则

流控,降级,熔断的区别:流控超过频率就把请求完全屏蔽等频率降下来就继续提供服务,降级超过频率采用备用服务或者丢弃部分资源,等待一定时间以后继续提供服务。熔断直接停用服务,等一段时间后再去尝试是否可以调用服务。

降级策略:RT:一秒内的请求平均响应时间,时间窗口:等待的时间; 异常比例:一秒内的请求异常的数量/请求总数量;异常数:一分钟产生的异常个数

2.3.3 热点规则

热点参数流控规则是一种更细粒度的流控规则, 它允许将规则具体到参数上。

带参数的流控规则

第1步: 编写代码

java 复制代码
@RequestMapping("/order/message3")
@SentinelResource("message3")
public String message3(String name, Integer age) {
    return "message3" + name + age;
}

第2步: 配置热点规则

第3步: 分别用两个参数访问,会发现只对第一个参数限流了

热点规则增强使用

参数例外项允许对一个参数的具体值进行流控,编辑刚才定义的规则,增加参数例外项

2.3.4 授权规则

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源 访问控制的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过:

  • 若配置白名单,则只有请求来源位于白名单内时才可通过;
  • 若配置黑名单,则请求来源位于黑名单时不通过,其余的请求通过。

判断请求头/参数,确定是否为白名单/黑名单,下面是一个配置类,,请求发出的时候的该类就可以从url上获取request域的源标识。

java 复制代码
@Component
public class RequestOriginParserDefinition implements RequestOriginParser {

    //定义区分来源: 本质作用是通过request域获取到来源标识
    //app  pc
    //然后 交给流控应用 位置进行匹配
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String serviceName = request.getParameter("serviceName");
        if (StringUtils.isEmpty(serviceName)){
            throw new RuntimeException("serviceName is not empty");
        }
        return serviceName;
    }
}

分别访问:

http://localhost:8091/order/message1?serviceName=service

http://localhost:8091/order/message1?serviceName=service-A

记一次错误

shell 复制代码
java.util.ServiceConfigurationError: com.alibaba.csp.sentinel.init.InitFunc: Provider com.itheima.config.FilePersistence not found

因为没有配置 FilePersistence 而导致的sentinel无法使用。

2.3.5 系统规则---服务器维度的流控

系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、入口 QPS 、CPU 使用率和线程数五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量 (进入应用的流量) 生效。

  • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过 系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般 是 CPU cores * 2.5。
  • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。 CPU使用率:当单台机器上所有入口流量的 CPU使用率达到阈值即触发系统保护。
2.3.6 自定义异常返回

写个配置类,继承UrlBlockHandler,它会接受异常,然后运行blocked,可以在该函数里面写if,else语句判断异常类型,进行相对处理,实例代码:

java 复制代码
package com.itheima.config;

import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//自定义异常返回页面
@Component
public class ExceptionHandlerPage implements UrlBlockHandler {
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        response.setContentType("application/json;charset=utf-8");

        ResponseData responseData = null;
        //BlockException  异常接口,包含Sentinel的五个异常
        //  FlowException  限流异常
        //  DegradeException  降级异常
        //  ParamFlowException  参数限流异常
        //  AuthorityException  授权异常
        //  SystemBlockException  系统负载异常
        if (e instanceof FlowException) {
            responseData = new ResponseData(-1, "接口被限流了...");
        } else if (e instanceof DegradeException) {
            responseData = new ResponseData(-2, "接口被降级了...");
        }
        response.getWriter().write(JSON.toJSONString(responseData));
    }
}

@Data
@AllArgsConstructor//全参构造
@NoArgsConstructor
//无参构造
class ResponseData {
    private int code;
    private String message;
}
相关推荐
刘大辉在路上2 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
追逐时光者4 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql
初晴~4 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱581364 小时前
InnoDB 的页分裂和页合并
数据库·后端
小_太_阳5 小时前
Scala_【2】变量和数据类型
开发语言·后端·scala·intellij-idea
直裾5 小时前
scala借阅图书保存记录(三)
开发语言·后端·scala
黑胡子大叔的小屋5 小时前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
星就前端叭6 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
计算机毕设孵化场6 小时前
计算机毕设-基于springboot的校园社交平台的设计与实现(附源码+lw+ppt+开题报告)
spring boot·课程设计·计算机毕设论文·计算机毕设ppt·计算机毕业设计选题推荐·计算机选题推荐·校园社交平台