SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。
程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCloud 微服务系列项目开发
本文章是系列文章中的一篇
- 1、SpringCloud 项目基础工程搭建 【SpringCloud系列1】
- 2、SpringCloud 集成Nacos注册中心 【SpringCloud系列2】
- 3、SpringCloud Feign远程调用 【SpringCloud系列3】
- 4、SpringCloud Feign远程调用公共类抽取 【SpringCloud系列4】
- 5、SpringCloud 整合Gateway服务网关 【SpringCloud系列5】
- 6、SpringCloud 整合 Spring Security 认证鉴权【SpringCloud系列6】
- SpringCloud网关Gateway认证鉴权【SpringCloud系列7】
- SpringCloud Gateway 通过redis实现限流【SpringCloud系列8】
降级
指系统将某些业务或者接口的功能降低,可以是只提供部分功能,也可以是完全停掉所有功能
熔断
A 服务的 X 功能依赖 B 服务的某个接口,当 B 服务的接口响应很慢的时候,A 服务的 X 功能响应肯定也会被拖慢,进一步导致 A 服务的线程都被卡在 X 功能处理上,此时 A 服务的其他功能都会被卡住或者响应非常慢。这时就需要熔断机制了,即:A 服务不再请求 B 服务的这个接口,A 服务内部只要发现是请求 B 服务的这个接口就立即返回错误,从而避免 A 服务整个被拖慢甚至拖死。
限流
限流指只允许系统能够承受的访问量进来,超出系统访问能力的请求将被丢弃。
排队
限流是直接拒绝用户,排队是让用户等待一段时间。
在高并发的系统中,往往需要在系统中做限流,常见的限流方式:
- Hystrix适用线程池隔离,超过线程池的负载,走熔断的逻辑
- tomcat容器 通过限制它的线程数
- 通过时间窗口的平均速度来控制流量
常见的限流算法
- 计数器算法,一般会限制一秒钟的能够通过的请求数
- 漏桶算法, 算法内部有一个容器,类似生活用到的漏斗,当请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变
- 令牌桶算法,令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用
本文章实现的是集成阿里的Sentinel实现网关限流。Sentinel是SpringCloud Alibaba提供的微服务组件,能够从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
1 docker-compose快速部署alibaba sentinel
创建docker-compose.yaml文件
version: "3.2"
services:
sentinel:
image: matecloud/sentinel-dashboard:1.8.1
container_name: "sentinel-dashboard"
environment:
- TZ=Asia/Shanghai
- JAVA_OPTS= -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=sentinel -Dserver.servlet.session.timeout=7200
ports:
- 8088:8080
restart: on-failure
启动与关闭
#启动
docker-compose up -d
#关闭
docker-comopse stop
然后浏览器中访问 http://localhost:8088/#/dashboard/home
这里设置的用户名 sentinel 密码 sentinel
2 网关服务配置
首先是 pom.xml 中添加依赖
<!-- spring cloud gateway整合sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
application.yml 配置文件中主要指定以下三种配置:
- nacos的地址
- sentinel控制台的地址
- 网关路由的配置
- redis 配置的地址
server:
port: 10001
spring:
cloud:
## 整合sentinel,配置sentinel控制台的地址
sentinel:
#配置限流之后的响应内容
scg:
fallback:
# 两种模式:一种是response返回文字提示信息,一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
mode: response
# 响应的状态
response-status: 426
# 响应体
response-body: '{"code": 426,"message": "限流了,稍后重试!"}'
transport:
port: 8080
## 指定控制台的地址,默认端口8080
dashboard: localhost:8088
eager: true
然后重新启动网关项目,访问订单详情的接口
然后控制台中可以查看到具体的流量监控
3 Sentinel 网关流控
创建一个 FlowRule 来配置普通流控
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Component
public class SentinelConfig {
private static final String KEY="order-service";
@PostConstruct
private void init(){
initFlowQpsRule();
}
//流量控制规则
private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
//资源名 流控的服务名
FlowRule rule = new FlowRule(KEY);
//1秒内请求的次数
rule.setCount(1);
//RuleConstant.FLOW_GRADE_QPS 1秒内访问限制
//RuleConstant.FLOW_GRADE_THREAD 线程数量
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//来源
rule.setLimitApp("default");
}
}
这个配置相当于是1秒内完成1次的响应请求,其余的提示限流
这样是写在代码中的硬编码的初始化的流控规则 ,本项目使用 nocas 来动态配置初始化的流控规则 。
4 Nacos 动态配置流控规则
网关项目中添加pom.xml依赖
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--sentinel对Nacos数据源的支持依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
修改网关中的 application.yml 配置文件如下:(主要是添加 datasource 节点)
server:
port: 10001
spring:
application:
name: '@project.name@'
redis:
database: 0 # Redis数据库索引(默认为0)
host: localhost # Redis服务器地址
port: 6379 # Redis服务器连接端口
password: 12345678 # Redis服务器连接密码(默认为空)
cloud:
## 整合sentinel,配置sentinel控制台的地址
sentinel:
#配置限流之后的响应内容
scg:
fallback:
# 两种模式:一种是response返回文字提示信息,一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
mode: response
# 响应的状态
response-status: 426
# 响应体
response-body: '{"code": 426,"message": "限流了,稍后重试!"}'
transport:
port: 8080
## 指定控制台的地址,默认端口8080
dashboard: localhost:8088
eager: true
datasource:
r1:
nacos:
# nacos地址
server-addr: localhost:8848
# nacos中配置文件的data-id
data-id: ${spring.application.name}-sentinel
# nacos 分组
group-id: DEFAULT_GROUP
# 规则类型 流控
rule-type: flow
r2:
nacos:
server-addr: localhost:8848
data-id: ${spring.application.name}-sentinel-degrade
group-id: DEFAULT_GROUP
rule-type: degrade
nacos:
server-addr: localhost:8848 # nacos地址
在这里配置的 data-id 要与 nacos 中的配置文件名称对应起来,我的网关项目服务名称为 gateway-api ,所以在 nacos 中创建 两个配置如下
4.1 流控规则 gateway-api-sentinel
格式是 JSON ,是一个数组,数组中每个Json对象表示一条流控规则。
[
{
"resource": "/**",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
重启网关,sentine 控制台显示
4.2 gateway-api-sentinel-degrade 文件降级规则
[
{
"count":500,
"grade":0,
"limitApp":"default",
"minRequestAmount":5,
"resource":"order-service",
"slowRatioThreshold":1,
"statIntervalMs":1000,
"timeWindow":100
}
]
Sentinel 控制台