一、基础概念
服务限流/熔断
服务限流目的是为了更好的保护我们的服务,在高并发的情况下,如果客户端请求的数量达到一定极限(后台可以配置阈值),请求的数量超出了设置的阈值,开启自我的保护,直接调用我们的服务降级的方法,不会执行业务逻辑操作,直接走本地falback的方法,返回一个友好的提示
服务降级
在高并发的情况下, 防止用户一直等待,采用限流/熔断方法,使用服务降级的方式返回一个友好的提示给客户端,不会执行业务逻辑请求,直接走本地的falback的方法。eg: 提示语:当前排队人数过多,稍后重试~
服务的雪崩效应
默认的情况下,Tomcat或者是Jetty服务器只有一个线程池去处理客户端的请求,
这样的话就是在高并发的情况下,如果客户端所有的请求都堆积到同一个服务接口上,
那么就会产生tomcat服务器所有的线程都在处理该接口,可能会导致其他的接口无法访问。
eg: 假设我们的tomcat线程最大的线程数量是为20,这时候客户端如果同时发送100个请求会导致有80个请求暂时无法访问,就会转圈。
服务雪崩的解决方案:服务的隔离的机制
服务的隔离机制分为信号量和线程池隔离模式
- 服务的线程池隔离机制:每个服务接口都有自己独立的线程池,互不影响,缺点就是占用cpu资源非常大。
- 服务的信号量隔离机制:最多只有一定的阈值线程数处理我们的请求,超过该阈值会拒绝请求。
二、Sentinel与hytrix区别
前哨以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。
前哨具有以下特征:
- 1.丰富的应用场景:前哨兵承接了阿里巴巴近10年的双十一大促流的核心场景,例如秒杀(即突然流量控制在系统容量可以承受的范围),消息削峰填谷,传递流量控制,实时熔断下游不可用应用等。
- 2.完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接收应用的单台机器秒级数据,甚至500台以下规模的整合的汇总运行情况。
广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的集成模块,例如与Spring Cloud,Dubbo,gRPC的整合。您只需要另外的依赖并进行简单的配置即可快速地接入Sentinel。 - 3.完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适应动态数据源等。
Sentinel中文文档介绍:sentinel中文文档
三、SpringBoot项目整合Sentinel
1.Maven依赖的配置
| 1 2 3 4 5 6 7 8 9 10 | ```
org.springframework.cloud spring-cloud-alibaba-sentinel 0.2.2.RELEASE org.springframework.boot spring-boot-starter-actuator
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
#### [](#2-%E9%A1%B9%E7%9B%AE%E5%90%AF%E5%8A%A8%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%99%90%E6%B5%81%E8%A7%84%E5%88%99 "2.项目启动自动配置限流规则")2.项目启动自动配置限流规则
常量类:
| ```
1 2 3 4 5
``` | ```
public interface SentinelConstant { //限流名称 String GETORDER_KEY = "getOrder"; }
``` |
| ------------------ | ------------------------------------------------------------------------------------------------ |
SentinelInit:
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
``` | ```
@Component public class SentinelInit implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { List<FlowRule> rules = new ArrayList<FlowRule>(); FlowRule rule1 = new FlowRule(); rule1.setResource(SentinelConstant.GETORDER_KEY); // QPS控制在2以内 rule1.setCount(1); // QPS限流 rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); rule1.setLimitApp("default"); rules.add(rule1); FlowRuleManager.loadRules(rules); System.out.println("...限流配置初始化成功.."); } }
``` |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
#### [](#3%E3%80%81%E9%9D%9E%E6%B3%A8%E8%A7%A3%E5%BD%A2%E5%BC%8F%E9%85%8D%E7%BD%AE%E5%88%B0%E6%8E%A5%E5%8F%A3 "3、非注解形式配置到接口")3、非注解形式配置到接口
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
``` | ```
@RequestMapping("/getOrder") public String getOrders() { Entry entry = null; try { entry = SphU.entry(SentinelConstant.GETORDER_KEY); // 执行我们服务需要保护的业务逻辑 return "getOrder接口"; } catch (Exception e) { e.printStackTrace(); return "该服务接口已经达到上线!"; } finally { // SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常 if (entry != null) { entry.exit(); } } }
``` |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
#### [](#4%E3%80%81%E6%B3%A8%E8%A7%A3%E5%BD%A2%E5%BC%8F%E9%85%8D%E7%BD%AE%E5%88%B0%E6%8E%A5%E5%8F%A3 "4、注解形式配置到接口")4、注解形式配置到接口
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
``` | ```
/** * fallback 服务降级执行本地方法 * blockHandler 限流/熔断出现异常执行的方法 * value 指定我们的资源名称 * @return */ @RequestMapping("/orderTinner") @SentinelResource(value = SentinelConstant.GETORDER_KEY,blockHandler = "getorderQpsException") public String orderTinner() { return "orderTinner"; } public String getorderQpsException(BlockException e){ e.printStackTrace(); return "该接口已经被限流了!!!!"; }
``` |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
### [](#%E5%9B%9B%E3%80%81%E6%8E%A7%E5%88%B6%E5%8F%B0sentinel "四、控制台sentinel")四、控制台sentinel
#### [](#1-%E4%B8%8B%E8%BD%BDjar%E5%8C%85 "1.下载jar包")1.下载jar包
参考官网
#### [](#2-%E8%BF%90%E8%A1%8C%E5%91%BD%E4%BB%A4 "2.运行命令")2.运行命令
| ```
1
``` | ```
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar /Users/jinping/Desktop/sentinel-dashboard-1.7.2.jar
``` |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
8718属于 界面端口号 8719 属于api通讯的端口号
#### [](#%E4%BA%94%E3%80%81SpringBoot%E6%95%B4%E5%90%88Sentinel%E4%BB%AA%E8%A1%A8%E7%9B%98-%E9%85%8D%E7%BD%AE "五、SpringBoot整合Sentinel仪表盘 配置")五、SpringBoot整合Sentinel仪表盘 配置
##### [](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6 "配置文件")配置文件
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14
``` | ```
spring: application: name: tinner-member cloud: nacos: discovery: #nacos注册地址 server-addr: 127.0.0.1:8848 sentinel: transport: dashboard: 127.0.0.1:8718 eager: true server: port: 8082
``` |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
##### [](#%E5%9F%BA%E4%BA%8E%E5%B9%B6%E5%8F%91%E6%95%B0%E9%87%8F%E5%A4%84%E7%90%86%E9%99%90%E6%B5%81 "基于并发数量处理限流")基于并发数量处理限流

\
每次最多只会有一个线程处理该业务逻辑,超出该阈值的情况下,直接拒绝访问
##### [](#%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81 "测试代码")测试代码
| ```
1 2 3 4 5 6 7 8 9 10 11
``` | ```
@SentinelResource(value = "getOrderThrad", blockHandler = "getOrderQpsException") @RequestMapping("/getOrderThrad") public String getOrderThrad() { System.out.println(Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (Exception e) { } return "getOrderThrad"; }
``` |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
### [](#%E5%85%AD%E3%80%81Sentinel%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E8%A7%84%E5%88%99%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96 "六、Sentinel如何保证规则的持久化")六、Sentinel如何保证规则的持久化
默认的情况下Sentinel的规则是存放在内存中,如果Sentinel客户端重启后,Sentinel数据规则可能会丢失。\
解决方案:**Sentinel持久化机制支持四种持久化的机制。**
* 1.本地文件
* 2.携程阿波罗
* 3.Nacos
* 4.Zookeeper

