文章目录
- 🚏 第十七章 SpringCloud Alibaba入门简介
- 🚬 一、为什么使用Alibaba
- 🚭 1、spring netflix进入维护模式
- 🚭 Spring cloud alibaba
- 🚬 二、如何使用?
- 🚬 三、版本对应
- 🚏 第十八章 服务注册和配置中心
- 🚬 一、是什么
- 🚭 1、nacos(NAming COnfiguration Service):服务注册和配置中心
- 🚭 2、Nacos 概念
- 🚭 3、架构
- 🛹 基本架构及概念
- 🛹 逻辑架构及其组件介绍
- 🛹 领域模型
- 🚬 二、Nacos2.0
- 🚬 三、与其他注册中心对比
- 🚬 四、切换
- 🚬 五、下载
- 🚬 六、注册中心功能
- 🚭 1、服务提供者1
- 🚭 2、服务提供者2
- 🚭 3、服务消费者
- 🚭 4、整合feign
- 🛹 1、在pom中导入
- 🛹 2、在主启动类上加上@EnableFeignClients,激活feign。
- 🛹 3、新建feign接口
- 🛹 4、controller新写方法
- 🚬 七、服务注册中心对比
- 🚭 1、Nacos 生态图
- 🚭 2、Nacos和CAP
- 🚭 3、对比其他注册中心
- 🚬 八、配置中心功能
- 🚭 1、创建工程nacos-client7777
- 🛹 1、pom
- 🛹 2、application.yml
- 🛹 3、bootstrap.yml
- 🛹 5、主启动类
- 🛹 6、controller
- 🛹 7、在Nacos中添加配置信息
- 🛹 8、测试:
- 🛹 9、更改配置,在进行测试
- 🚭 2、分类配置
- 🛹 1、dataid方案(就是nacos的文件名)
- 🛹 2、Group方案(默认DEFAULT_GROUP)
- 🛹 3、namespace方案(默认public)
- 🚬 九、集群和持久化配置(重要)
- 🚭 1、Nacos部署环境
- 🚭 2、Nacos支持三种部署模式
- 🚭 3、单机模式下运行Nacos
- 🚭 4、单机模式支持mysql
- 🚭 5、集群部署说明
- 🛹 预备环境准备
- 🛹 下载源码或者安装包
- 🛹 配置集群配置文件
- 🛹 确定数据源
- 🛹 启动服务器
- 🛹 结合nginx
- 🛹 项目配置获取
- 🚏 第十九章 SpringCloud Alibaba Sentinel实现熔断与限流
- 🚬 一、简介
- 🚬 二、下载
- 🚬 三、初始化演示工程
- 🚭 cloudalibaba-sentinel-service8000
- 🚬 四、流量控制
- 🚭 (1)qps 直接 快速失败
- 🚭 (2)并发 直接
- 🚭 (3)qps 关联失败
- 🚭 (4)qps 链路
- 🛹 新增GoodsService
- 🛹 配置文件
- 🛹 配置规则
- 🚭 (5)warm up
- 🚭 (6)匀速排队
- 🚬 五、熔断降级
- 🚭 (1)概述
- 🚭 (2)熔断策略
- 🛹 慢调用比例 (SLOW_REQUEST_RATIO)
- 🛹 异常比例 (ERROR_RATIO)
- 🛹 异常数 (ERROR_COUNT)
- 🚭 (3)熔断策略
- 🚭 (4)熔断器事件监听
- 🚬 六、热点参数限流
- 🚭 (1)概念
- 🚭 (2)基本使用
- 🛹 依赖:
- 🛹 controller
- 🛹 设置规则
- 🛹 测试访问
- 🛹 为了给调用方一个正确的值,改造
- 🚭 (3)例外情况
- 🛹 配置
- 🛹 测试访问
- 🚭 (4)热点参数规则说明
- 🚬 七、系统自适应限流
- 🚭 (1)背景
- 🚭 (2)系统规则
- 🚭 (3)原理
- 🚬 八、@SentinelResource
- 🚬 九、降级
- 🚭 (1)解释
- 🚭 (2)新建3个项目
- 🛹 cloudalibaba-sentinel-provider9001
- 🛹 cloudalibaba-sentinel-provider9002
- 🛹 cloudalibaba-consumer-nacos-consumer8000
- 🚭 (3)不同情况下 blockHandler与fallback情况
- 🛹 情况一:不配置
- 🛹 情况二:只配blockHandler
- 🛹 情况三:只配fallback
- 🛹 情况四:都进行配置
- 🛹 情况五:忽略某些异常
- 🚬 十、OpenFeign调用
- 🚬 十一、配置持久化
😹 作者: gh-xiaohe
😻 gh-xiaohe的博客
😽 觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!
🚏 第十七章 SpringCloud Alibaba入门简介
🚬 一、为什么使用Alibaba
🚭 1、spring netflix进入维护模式
https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now#spring-cloud-netflix-projects-entering-maintenance-mode
什么是维护模式:spring cloud团队将不会再向模块添加新功能,我们将修复block级别的bug以及安全问题,我们也会考虑并审查社区的小型pull request。我们打算继续支持这些模块,知道Greenwich版本被普遍采用至少一年
SpringCloud Netflix将不再开发新的组件
以下spring cloud netflix模块和响应的starter将进入维护模式:
- spring-cloud-netflix-archaius
- spring-cloud-netflix-hystrix-contract
- spring-cloud-netflix-hystrix-dashboard
- spring-cloud-netflix-hystrix-stream
- spring-cloud-netflix-hystrix
- spring-cloud-netflix-ribbon
- spring-cloud-netflix-turbine-stream
- spring-cloud-netflix-turbine
- spring-cloud-netflix-zuul
我们都知道SpringCloud版本迭代是比较快的,因而出现了很多重大ISSUE都还来不及Flix就又推另一个RELEASE了。进入维护模式意思就是目前以及以后一段时间SpingCloud Netflix提供的报务和功能就这么多了,不在开发新的组件和功能了。以后将以雏护和Merge分支Full Request为主。
🚭 Spring cloud alibaba
https://spring.io/projects/spring-cloud-alibaba
2018.10.31,spring cloud Alibaba正式入驻了Spring Cloud官方孵化器,并在Maven中央库发布了第一个版本
主要功能:
- 服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
- 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
- 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
- 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
- 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
- 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
- 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
组件:
- Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
- Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
- Alibaba Cloud OSS:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- Alibaba Cloud SchedulerX:阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
- Alibaba Cloud SMS:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
🚬 二、如何使用?
- Spring官网:https://spring.io/projects/spring-cloud-alibaba
- GitHub:https://github.com/alibaba/spring-cloud-alibaba
- GitHub中文文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
- Spring Cloud Alibaba参考文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html
按照官网一步一步来 https://spring.io/projects/spring-cloud-alibaba#learn
新建父工程
<dependencyManagement>
<dependencies>
<!-- SpringCloud Alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
🚬 三、版本对应
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version |
---|---|---|---|---|---|
2021.0.1.0* | 1.8.3 | 1.4.2 | 4.9.2 | 2.7.15 | 1.4.2 |
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2021.0.1.0 | Spring Cloud 2021.0.1 | 2.6.3 |
🚏 第十八章 服务注册和配置中心
🚬 一、是什么
官方文档(Nacos地址):https://nacos.io/zh-cn/docs/what-is-nacos.html
github地址: https://github.com/alibaba/Nacos
🚭 1、nacos(NAming COnfiguration Service):服务注册和配置中心
Nacos = Eureka + Config + Bus
- 替代Eureka做服务注册中心
- 替代Config做服务配置中心
🚭 2、Nacos 概念
🚭 3、架构
🛹 基本架构及概念
🛹 逻辑架构及其组件介绍
🛹 领域模型
数据模型:
- Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是 DEFAULT_GROUP。
🚬 二、Nacos2.0
新增功能
-
1、长连接功能
-
2、鉴权插件
-
3、配置加密
Nacos2.0版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口。新增端口是在配置的主端口(server.port)基础上,进行一定偏移量自动生成。
🚬 三、与其他注册中心对比
服务注册与服务框架 | CAP模型 | 控制台管理 | 社区活跃度 |
---|---|---|---|
Eureka | AP高可用 | 支持 | 低(2.x版本闭源) |
Zookeeper | CP一致 | 支持 | 中 |
Consul | CP | 支持 | 高 |
Nacos | AP+CP | 支持 | 高 |
🚬 四、切换
nacos可以切换 AP 和 CP ,可使用如下命令切换成CP模式
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
🚬 五、下载
1.下载地址: https://github.com/alibaba/nacos/releases
直接下载网址:https://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.zip
2.下载压缩包以后解压,进入bin目录,打开dos窗口,执行startup命令启动它。
startup.cmd -m standalone # (standalone代表着单机模式运行,非集群模式)
3.端口号8848
4.可访问 : http://localhost:8848/nacos/index.html 地址,默认账号密码都是nacos
🚬 六、注册中心功能
急速构建
父工程中版本锁定
<!--版本锁定 这里,规定了子工程中,cloud和alibaba -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
🚭 1、服务提供者1
新建模块 nacos-provider8000
<!--SpringCloud Alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
server:
port: 8000
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
主启动类
@EnableDiscoveryClient // 注册中心的客户端
controller 显示server.port
package com.ydlclass.nacos.provider8000.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Value("${server.port}")
Integer port;
@GetMapping("/findById/{id}")
public String findById(@PathVariable("id")Integer id){
//业务逻辑
return "nacos provider.port:"+port+"|id:"+id;
}
}
🚭 2、服务提供者2
新建模块 nacos-provider8001
<!--SpringCloud Alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
server:
port: 8001
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
主启动类
@EnableDiscoveryClient // 注册中心的客户端
controller 显示server.port
package com.ydlclass.nacos.provider8000.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Value("${server.port}")
Integer port;
@GetMapping("/findById/{id}")
public String findById(@PathVariable("id")Integer id){
//业务逻辑
return "nacos provider.port:"+port+"|id:"+id;
}
}
🚭 3、服务消费者
新建模块 nacos-conusmer9000
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringCloud Alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
server:
port: 9000
spring:
application:
name: nacos-consumer
cloud:
loadbalancer:
ribbon:
enabled: false # 禁用ribbon
nacos:
discovery:
server-addr: localhost:8848
主启动类
@EnableDiscoveryClient
注册RestTemplate
package com.ydlclass.nacos.conusmer9000.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean @LoadBalanced //loadbalancer 客户端负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); } }
controller调用
package com.ydlclass.nacos.conusmer9000.controller; @RestController @RequestMapping("/order") public class OrderController { @Autowired private RestTemplate restTemplate; @GetMapping("/add/{id}") public String add(@PathVariable("id") Integer id) { //业务逻辑 String url = "http://nacos-provider/goods/findById/" + id; String result = restTemplate.getForObject(url, String.class); // 返回值的类型 return result; } }
测试:http://localhost:9000/order/add/1
🚭 4、整合feign
🛹 1、在pom中导入
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
🛹 2、在主启动类上加上@EnableFeignClients,激活feign。
🛹 3、新建feign接口
package com.ydlclass.nacos.conusmer9000.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("nacos-provider")
public interface GoodsFeign {
@GetMapping("/goods/findById/{id}")
public String findById(@PathVariable("id")Integer id);
}
🛹 4、controller新写方法
@Autowired
GoodsFeign goodsFeign;
/**
* 使用feign调用
*/
@GetMapping("/add/{id}")
public String add(@PathVariable("id") Integer id) {
String result = goodsFeign.findById(id);
return result;
}
测试:http://localhost:9000/order/add2/1
🚬 七、服务注册中心对比
🚭 1、Nacos 生态图
🚭 2、Nacos和CAP
🚭 3、对比其他注册中心
A:可用性 C:一致性 P:分区容错性
-
Nacos默认AP。
-
切换CP:
-
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
-
🚬 八、配置中心功能
动态刷新 配置中心 功能
🚭 1、创建工程nacos-client7777
🛹 1、pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
<!-- nacos config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--SpringCloud Alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
🛹 2、application.yml
spring:
profiles:
active: dev #表示开发环境
🛹 3、bootstrap.yml
bootstrap.yml 的优先级 高于 application.yml
# nacos配置
server:
port: 7777
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
#${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
🛹 5、主启动类
@EnableDiscoveryClient
🛹 6、controller
package com.ydlclass.nacos.client7777.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
@RefreshScope // 开启刷新功能
public class ConfigClientController {
@Value("${name}")
String name;
@GetMapping("/name")
public String name() {
return name;
}
}
🛹 7、在Nacos中添加配置信息
https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html
🛹 8、测试:
http://localhost:7777/config/name
🛹 9、更改配置,在进行测试
再次访问接口。说明bus的功能也实现了。
🚭 2、分类配置
问题1:实际开发中,通常一个系统会准备dev/test/prod环境。如何保证环境启动时服务能正确读取nacos上相应环境的配置文件?
答案:namespace区分
问题2:一个大型分布式微服务系统有很多微服务子项目,每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境。那怎么对微服务配置进行管理呢?
答案:用group把不同的微服务划分到同一个分组里面去Service就是微服务,一个service可以包含多个cluster集群,nacos默认cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
比方说为了容灾,将service微服务分别部署在了北京机房和上海机房,这是就可以给北京机房的service微服务起一个集群名称BJ,给上海的service微服务起一个集群名称SH,还可以尽量让同一个机房的微服务互相调用,以提升效率。
🛹 1、dataid方案(就是nacos的文件名)
指定spring.profile.active和配置文件的dataID来使不太环境下读取不同的配置 配置空间+配置分组+新建dev和test两个dataid:就是创建-后不同的两个文件名nacos-config-client-dev.yaml、nacos-config-client-test.yaml 通过IDEA里的spring.profile.active属性就能进行多环境下配置文件的读取。
🛹 2、Group方案(默认DEFAULT_GROUP)
在nacos创建配置文件时,给文件指定分组。 在IDEA中该group内容 实现的功能:当修改开发环境时,只会从同一group中进行切换。
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: BJ_GROUP
🛹 3、namespace方案(默认public)
这个是不允许删除的,可以创建一个新的命名空间,会自动给创建的命名空间一个流水号。 在nacos新建命名空间,自动出现e79f32ec-974a-4e90-9086-3ae5c64db7e3
在IDEA的yml中指定命名空间namespace: e79f32ec-974a-4e90-9086-3ae5c64db7e3
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: BJ_GROUP
namespace: e79f32ec-974a-4e90-9086-3ae5c64db7e3
最后,dataid、group、namespace 三者关系如下:(不同的dataid,是相互独立的,不同的group是相互隔离的,不同的namespace也是相互独立的)
🚬 九、集群和持久化配置(重要)
存储的数据在nacos\data\derby-data 中
Nacos部署手册 https://nacos.io/zh-cn/docs/deployment.html
🚭 1、Nacos部署环境
🚭 2、Nacos支持三种部署模式
🚭 3、单机模式下运行Nacos
🚭 4、单机模式支持mysql
nacos\conf 下有sql文件
建议:把application.properties 中Msyql 相关的注释 打开 按照版本格式书写,版本不同格式略微有不同
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://localhost:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=nacos_devtest db.password=youdontknow
再以单机模式启动nacos,nacos所有写嵌入式数据库的数据都写到了mysql
🚭 5、集群部署说明
集群部署说明 :https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html
🛹 预备环境准备
🛹 下载源码或者安装包
🛹 配置集群配置文件
🛹 确定数据源
🛹 启动服务器
🛹 结合nginx
1、上传nginx源码包
2、修改配置文件
用户的请求访问5555,让nginx做一下负载均衡,负载到 proxy_pass gh 中
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream cluster{ server 192.168.28.1:6666; server 192.168.28.1:7777; server 192.168.28.1:8888; } server { listen 5555; server_name localhost; location / { proxy_pass http://cluster; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
3、启动nginx
4、测试访问
http://192.168.246.128:5555/nacos/index.html
🛹 项目配置获取
Nacos 内嵌数据库转到MySQL 数据库
1、新建配置文件
2、项目修改获取配置文件地址
# bootstrap.yml 的优先级 高于 application.yml
# nacos配置
server:
port: 7777
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
# server-addr: localhost:8848 #Nacos服务注册中心地址
# config:
# server-addr: localhost:8848 #Nacos作为配置中心地址
# file-extension: yaml #指定yaml格式的配置
# 外部 Nacos 搭建了集群,使用Nginx代理
server-addr: localhost:5555
config:
server-addr: localhost:5555
file-extension: yaml #指定yaml格式的配置
group: BJ_GROUP
namespace: 1ee8cb1c-856f-45e7-b433-f2f131ea8db1 # 命名空间
# ${prefix}-${spring.profiles.active}.${file-extension}
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml
# prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
# spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。
# 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
# file-exetension 为配置内容的数据格式,目前只支持 properties 和 yaml 类型。
🚏 第十九章 SpringCloud Alibaba Sentinel实现熔断与限流
🚬 一、简介
一句话:就是hystrix的替代!
官网:https://sentinelguard.io/zh-cn/docs/quick-start.html
github地址:https://github.com/alibaba/sentinel
桌面sentinel.png图片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J02Cizyr-1676296873399)(SpringCloud.assets/sentinel.png)]
🚬 二、下载
下载:https://github.com/alibaba/Sentinel/releases
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5UauL3z-1676296873400)(SpringCloud.assets/image-20220424155816578.38f9071b.png)]
运行
java -jar sentinel-dashboard-1.8.4.jar
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYNuK3Cn-1676296873400)(SpringCloud.assets/image-20220424155846911.9e8b14bf.png)]
http://localhost:8080
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0uj0Axma-1676296873400)(SpringCloud.assets/image-20220424121030210.3df6fbd1.png)]
账号和密码都是sentinel
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jH4FOY8J-1676296873401)(SpringCloud.assets/image-20220424121050706.12aada39.png)]
🚬 三、初始化演示工程
🚭 cloudalibaba-sentinel-service8000
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ynuWFEXg-1676296873401)(SpringCloud.assets/image-20230131114736773.png)]
pom
<dependencies> <!-- SpringCloud ailibaba nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <!-- SpringCloud ailibaba sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
yml
8080是 外界的用户想要看控制 面板的端口
程序8000 和 dashboard 8080 的交互端口是 8719
server: port: 8000 spring: application: name: cloudalibaba-sentinal-service cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: dashboard: localhost:8080 # 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口 port: 8719
主启动类
@EnableDiscoveryClient
controller
@RestController public class FlowLimitController { @GetMapping("/testA") public String testA() { return "----testA"; } @GetMapping("/testB") public String testB() { return "----testB"; } }
测试
**启动8000,然后刷新sentinel后台页面(因为sentinel采用懒加载策略,所以需要调用服务后才在后台显示) **
在浏览器分别输入请求,然后刷新sentinel后台页面
http://localhost:8000/testA http://localhost:8000/testB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aB76wSyg-1676296873401)(SpringCloud.assets/image-20220424163655481.45b27ad3.png)]
🚬 四、流量控制
https://sentinelguard.io/zh-cn/docs/flow-control.html
动态加载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tZeDlG0b-1676296873401)(SpringCloud.assets/image-20230131193205215.png)]
- 资源名:唯一名称,默认请求路径
- 针对来源:sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)A调用B时,可以限制只允许A进行调用
- 阈值类型/单机值:
- QPS(每秒钟的请求数量):当调用该api就QPS达到阈值的时候,进行限流
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hCxh9ixF-1676296873402)(SpringCloud.assets/image-20220424174426829.7aeed4f5.png)]
- 线程数:当调用该api的线程数达到阈值的时候,进行限流
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NOIhTWjZ-1676296873402)(SpringCloud.assets/image-20220424174544692.762c6a35.png)]
- 是否集群:不需要集群
- 流控模式:
- 直接:api达到限流条件时,直接限流。分为QPS和线程数
- 关联:当关联的资到阈值时,就限流自己。别人惹事,自己买单
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
- 流控效果:
- 快速失败:直接抛异常 Blocked by Sentinel (flow limiting)
- warm up:根据codeFactor(冷加载因子,默认3)的值,从阈值codeFactor,经过预热时长,才达到设置的QPS阈值
- 排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS 或线程数模式 | QPS 模式 |
limitApp | 流控针对的调用来源 | default ,代表不区分调用来源 |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流 | 直接拒绝 |
🚭 (1)qps 直接 快速失败
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugJx9JNx-1676296873402)(SpringCloud.assets/image-20230131194432813.png)]
🚭 (2)并发 直接
controller
@GetMapping("/testA") public String testA(){ //业务逻辑比价复杂 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } return "itlils testA"; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8eaPcmZT-1676296873403)(SpringCloud.assets/image-20220424174723161.cfdc7598.png)]
浏览器开两个tab分别快速访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UAi6zYhF-1676296873403)(SpringCloud.assets/image-20220424174110634.2ba9c366.png)]
🚭 (3)qps 关联失败
前提:B接口坏了,所以A接口不能用了
设置B A的失败策略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kz0vd0Hp-1676296873403)(SpringCloud.assets/image-20220425162627537.2580ddf1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jebRqMCs-1676296873404)(SpringCloud.assets/image-20220425162638896.edd61661.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3DflXUZ-1676296873404)(SpringCloud.assets/image-20230131201902444.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZTtyNOCW-1676296873404)(SpringCloud.assets/image-20230131203352902.png)]
🚭 (4)qps 链路
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LAuqD0T3-1676296873404)(SpringCloud.assets/image-20230131210015294.png)]
🛹 新增GoodsService
@Service
public class GoodsService {
@SentinelResource("querygoods")
public void queryGoods(){
System.err.println("查询商品");
}
}
🛹 配置文件
从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,导致链路限流不生效。
从1.7.0版本开始,官方在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context,将其配置为false即可根据不同的URL进行链路限流。
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的端口
port: 8719
web-context-unify: false # 关闭收敛的URL
有资源了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ai4tZz9K-1676296873405)(SpringCloud.assets/image-20220425171005883.371936e1.png)]
🛹 配置规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4reEzkEN-1676296873405)(SpringCloud.assets/image-20220425171040497.8501dfdf.png)]
快速调用A,对A进行了限制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiFrTY0R-1676296873405)(SpringCloud.assets/image-20220425171143687.8ac44443.png)]
快速调用B
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Liwa3CFG-1676296873405)(SpringCloud.assets/image-20220425171157383.0e068415.png)]
🚭 (5)warm up
https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。
详细文档可以参考 流量控制 - Warm Up 文档open in new window,具体的例子可以参见 WarmUpFlowDemoopen in new window。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awYsnHlN-1676296873406)(SpringCloud.assets/image-20230131211758432.png)]
一开始,一秒钟这个接口只能访问三次(10的三分之一)请求,5秒钟之后才能达到一秒钟10个请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aW4db8qw-1676296873406)(SpringCloud.assets/image-20220425172716814.bad66766.png)]
🚭 (6)匀速排队
https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
详细文档可以参考 流量控制 - 匀速器模式open in new window,具体的例子可以参见 PaceFlowDemoopen in new window。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UAhCr16K-1676296873406)(SpringCloud.assets/image-20230131214119708.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcUD0d8M-1676296873406)(SpringCloud.assets/image-20230131214314214.png)]
🚬 五、熔断降级
https://sentinelguard.io/zh-cn/docs/circuit-breaking.html
🚭 (1)概述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KHlk3we1-1676296873407)(SpringCloud.assets/image-20230130221104184.png)]
🚭 (2)熔断策略
桌面熔断策略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJg1iuGL-1676296873407)(SpringCloud.assets/image-20230130221527824.png)]
🛹 慢调用比例 (SLOW_REQUEST_RATIO)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jo4WCfPX-1676296873407)(SpringCloud.assets/image-20220425190913439.cb66dd3a.png)]
代码
@GetMapping("/testC/{id}") public String testC(@PathVariable("id")Integer id){ if(id==10){ //复杂的业务逻辑 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } return "itlils testC"; }
设置策略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vouRZ3wB-1676296873407)(SpringCloud.assets/image-20230201115250026.png)]
一直访问10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n0aJCljP-1676296873408)(SpringCloud.assets/image-20220425192753272.52de37f3.png)]
过一会儿,访问10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GLXszhDL-1676296873408)(SpringCloud.assets/image-20220425193646731.52ec05e0.png)]
🛹 异常比例 (ERROR_RATIO)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wa5Sc82Q-1676296873408)(SpringCloud.assets/image-20230201120002738.png)]
代码
@GetMapping("/testD/{id}") public String testD(@PathVariable("id")Integer id){ if(id==10){ //异常调用 int a=1/0; } return "itlils testD"; }
设置策略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-izWIVcW7-1676296873408)(SpringCloud.assets/image-20230201120446295.png)]
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CtBO8Ghf-1676296873409)(SpringCloud.assets/image-20220426115942858.dc5aab96.png)]
疯狂访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LYi6Pvsv-1676296873409)(SpringCloud.assets/image-20220426120122888.ff7a66d7.png)]
过2秒钟后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mhgln6Cx-1676296873409)(SpringCloud.assets/image-20220426120218008.69e6cf5b.png)]
🛹 异常数 (ERROR_COUNT)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMKJS1GP-1676296873409)(SpringCloud.assets/image-20230201120648023.png)]
代码
@GetMapping("/testE/{id}") public String testE(@PathVariable("id")Integer id){ if(id==10){ //异常调用 int a=1/0; } return "itlils testE"; }
配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibM3WF7h-1676296873410)(SpringCloud.assets/image-20230201120849941.png)]
疯狂测试http://localhost:8000/demo/testE/10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pJkQiSrx-1676296873410)(SpringCloud.assets/image-20220426161032712.08aa284c.png)]
过2秒 测试http://localhost:8000/demo/testE/1 状态正常
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZV4di2p-1676296873410)(SpringCloud.assets/image-20220426161101190.91a227bb.png)]
🚭 (3)熔断策略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kV81OBw2-1676296873410)(SpringCloud.assets/image-20230130221406197.png)]
🚭 (4)熔断器事件监听
Sentinel 支持注册自定义的事件监听器监听熔断器状态变换事件(state change event)。示例:
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
if (newState == State.OPEN) {
// 变换至 OPEN state 时会携带触发时的值
System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),
TimeUtil.currentTimeMillis(), snapshotValue));
} else {
System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),
TimeUtil.currentTimeMillis()));
}
});
🚬 六、热点参数限流
https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html
OR
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
🚭 (1)概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OpJjJxdh-1676296873411)(SpringCloud.assets/image-20230202212145309.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vmqdAeBW-1676296873411)(SpringCloud.assets/image-20220426162234051.97b222f7.png)]
🚭 (2)基本使用
🛹 依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.8.4</version>
</dependency>
<version>x.y.z</version> # 表示最新版本
如何查询最新版本
地址链接:https://search.maven.org/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xinoeOT7-1676296873411)(SpringCloud.assets/image-20230202213217746.png)]
🛹 controller
/**
* 热点参数限流
*/
@GetMapping("/order")
@SentinelResource(value = "hotKeys")
public String order(@RequestParam(value = "goodsId",required = false)String goodsId, // required = false 非必传
@RequestParam(value = "userId",required = false)String userId){
//业务逻辑
return "用户下单成功";
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BuYiUPuZ-1676296873411)(SpringCloud.assets/image-20230202215129170.png)]
🛹 设置规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pcMAqifG-1676296873412)(SpringCloud.assets/image-20230202215835895.png)]
🛹 测试访问
快速访问:http://localhost:8000/demo/order?goodsId=1&userId=10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5OkBsLIC-1676296873412)(SpringCloud.assets/image-20220426163435037.9d2b6d64.png)]
2s内访问一次:http://localhost:8000/demo/order?goodsId=1&userId=10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thoKty4C-1676296873412)(SpringCloud.assets/image-20230202221531714.png)]
快速访问,此时没有带限制的 goodsId ,一直成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEHVOOyB-1676296873413)(SpringCloud.assets/image-20220426163635673.dab246f4.png)]
说明设置限制源代码第一个参数,成功了。
🛹 为了给调用方一个正确的值,改造
/**
* 热点参数限流 v2
*/
@GetMapping("/order")
@SentinelResource(value = "hotKeys",blockHandler = "block_order")
public String order(@RequestParam(value = "goodsId",required = false)String goodsId, // required = false 非必传
@RequestParam(value = "userId",required = false)String userId){
//业务逻辑
return "用户下单成功";
}
public String block_order(@RequestParam(value = "goodsId",required = false)String goodsId
,@RequestParam(value = "userId",required = false)String userId,
BlockException ex){
// BlockException 记录错误日志
//logger.error(ex.getMessage()))
return "用户下单失败,请稍后重试";
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8vruuj4e-1676296873413)(SpringCloud.assets/image-20220426164323925.7320c157.png)]
🚭 (3)例外情况
秒杀情况下,某个参数 goodsId=100,最新手机id,单独设置阈值1000.
🛹 配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uNPkrmjT-1676296873413)(SpringCloud.assets/image-20230202223700999.png)]
🛹 测试访问
疯狂访问 http://localhost:8000/demo/order?goodsId=100&userId=10 不会降级
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OWwUmKyo-1676296873413)(SpringCloud.assets/image-20220426165532893.ec99b064.png)]
无聊:参数例外项,仅支持基本类型和字符串类型
无聊:
- 加一个:int a=1/0;
业务上的错,sentinel不会管:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hVvL0Y3D-1676296873414)(SpringCloud.assets/image-20220426165926729.de926f70.png)]
热点key限制,sentinel才会管,疯狂访问:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8DQvEacE-1676296873414)(SpringCloud.assets/image-20220426170005357.77d86ed3.png)]
🚭 (4)热点参数规则说明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWGEyLUx-1676296873415)(SpringCloud.assets/image-20230130222704291.png)]
🚬 七、系统自适应限流
https://sentinelguard.io/zh-cn/docs/system-adaptive-protection.html
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5UB27gu-1676296873415)(SpringCloud.assets/image-20230203212514816.png)]
🚭 (1)背景
🚭 (2)系统规则
🚭 (3)原理
本地图片系统自适应保护.png
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfOWuhqS-1676296873415)(SpringCloud.assets/image-20230130223015551.png)]
设置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Y65KTrb-1676296873416)(SpringCloud.assets/image-20230203213427863.png)]
测试http://localhost:8000/demo/testA
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvUliLCW-1676296873416)(SpringCloud.assets/image-20220426173225393.57ff7229.png)]
🚬 八、@SentinelResource
https://sentinelguard.io/zh-cn/docs/annotation-support.html
桌面@SentinelResource 注解.png
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rkIMsQyx-1676296873416)(SpringCloud.assets/@SentinelResource 注解png.png)]
blockHandler熔断测试
controller
//减库存接口 @GetMapping("/resume") @SentinelResource(value = "resume", blockHandlerClass = CommonBlockHandler.class, blockHandler = "handlerBlock2") public String resume(@RequestParam(value = "goodsId",required = false)String goodsId){ //业务逻辑 // int a=1/0; return "减库存成功"; }
CommonBlockHandler
import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.web.bind.annotation.RequestParam; /** * 公共 流速限制 类,给用户返回容易解析的对象 * 应返回: result<code,msg,data> */ public class CommonBlockHandler { /** * blockHandler函数默认需要和原方法在同一个类中,若希望使用其他类的函数, * 则可以指定blockHandlerClass为对应的类的Class对象,注意对应的函数必需为static函数,否则无法解析 */ public static String handlerBlock1(BlockException ex) { //logger.error(限流了) return "系统出错,请稍后再试!"; } public static String handlerBlock2(@RequestParam(value = "goodsId",required = false)String goodsId, BlockException ex){ //logger.error(限流了) return "系统出错,请稍后再试!handlerBlock2"; } }
测试 狂点http://localhost:8000/demo/resume?goodsId=100
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XkBOON9-1676296873417)(SpringCloud.assets/image-20220429165149264.31742c8d.png)]
🚬 九、降级
🚭 (1)解释
①断熔:微服务自己限流,不可用了
②降级:调用方,提供方错了,返回给客户一个友好对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kyOQcPFq-1676296873417)(SpringCloud.assets/image-20220429171002222.886e09b5.png)]
🚭 (2)新建3个项目
🛹 cloudalibaba-sentinel-provider9001
pom
<dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- SpringCloud ailibaba sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
yml
server: port: 9001 spring: application: name: cloudalibaba-sentinal-provider cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: dashboard: localhost:8080 # 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的端口 port: 8719 web-context-unify: false #关闭收敛URL
启动类 @EnableDiscoveryClient
controller
package com.ydlclass.provider.controller; import com.ydlclass.provider.domain.Goods; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/goods") public class GoodsController { @Value("${server.port}") Integer port; @GetMapping("/findById/{id}") public Goods findById(@PathVariable("id") Integer id){ //servive-->dao/mapper Goods goods=new Goods(); goods.setGoodId(id); goods.setPrice(123); goods.setTitle("手机.port:"+port); goods.setStock(10); return goods; } }
doamin
@Data @NoArgsConstructor @AllArgsConstructor public class Goods implements Serializable { private Integer goodId; private String title; private double price; private Integer stock; }
测试:http://localhost:9001/goods/findById/1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2OekHBrf-1676296873417)(SpringCloud.assets/image-20220429172614387.d0b8972c.png)]
🛹 cloudalibaba-sentinel-provider9002
同理。创建。
🛹 cloudalibaba-consumer-nacos-consumer8000
pom
<dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.1.1</version> </dependency> <!-- SpringCloud ailibaba sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
yml
server: port: 8000 spring: application: name: cloudalibaba-sentinal-consumer cloud: nacos: discovery: server-addr: localhost:8848 #nacos sentinel: transport: dashboard: localhost:8080 #sentinel port: 8719 #激活Sentinel对Feign的支持 feign: sentinel: enabled: true
配置类
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
controller
@RestController @RequestMapping("/order") public class OrderController { @Autowired RestTemplate restTemplate; @GetMapping("/add/{id}") public Goods add(@PathVariable("id")Integer id){ String url="http://cloudalibaba-sentinal-provider/goods/findById/"+id; Goods goods = restTemplate.getForObject(url, Goods.class); return goods; } }
goods 实体类 copy
@Data @NoArgsConstructor @AllArgsConstructor public class Goods implements Serializable { private Integer goodId; private String title; private double price; private Integer stock; }
测试
http://localhost:8000/order/add/1
发现负载均衡
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLVli3hW-1676296873418)(SpringCloud.assets/image-20220429175240918.42b7e40f.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rEDKykqK-1676296873418)(SpringCloud.assets/image-20220429175250362.f1ec683f.png)]
🚭 (3)不同情况下 blockHandler与fallback情况
🛹 情况一:不配置
if(id<0){
throw new IllegalArgumentException("非法参数");
}else if(id>100){
throw new NullPointerException("查无此商品");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kY2cY469-1676296873418)(SpringCloud.assets/image-20220429180414730.1efa7cfb.png)]
🛹 情况二:只配blockHandler
@SentinelResource(value = "add",blockHandler = "fail_add") public Goods fail_add(@PathVariable("id")Integer id, BlockException ex){ Goods goods =new Goods(); goods.setGoodId(-1); goods.setPrice(-1); goods.setStock(-1); goods.setTitle("限流之后的特殊对象"); return goods; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzTJnGNA-1676296873418)(SpringCloud.assets/image-20220429180844762.b34ac559.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmMJQsvD-1676296873419)(SpringCloud.assets/image-20220429180818990.1a6dac64.png)]
正常访问错id
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NACKtIdY-1676296873419)(SpringCloud.assets/image-20220429180927872.c247cf02.png)]
疯狂访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eVvpqOyZ-1676296873419)(SpringCloud.assets/image-20220429180940663.3e860e99.png)]
🛹 情况三:只配fallback
@SentinelResource(value = "add",fallback = "fallback_add")
//业务上的错的话
public Goods fallback_add(@PathVariable("id")Integer id, Throwable ex){
Goods goods =new Goods();
goods.setGoodId(-2);
goods.setPrice(-2);
goods.setStock(-2);
goods.setTitle("业务出错之后的特殊对象");
return goods;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GF4KnSmZ-1676296873419)(SpringCloud.assets/image-20220429181347488.902a9299.png)]
🛹 情况四:都进行配置
@SentinelResource(value = "add",blockHandler = "fail_add",fallback = "fallback_add")
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WhOdWrc6-1676296873420)(SpringCloud.assets/image-20220429181534288.e2839ace.png)]
-1 慢慢访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3sLqeH8S-1676296873420)(SpringCloud.assets/image-20220429181559790.b49e639a.png)]
-1 疯狂访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B4JHmgEs-1676296873420)(SpringCloud.assets/image-20220429181637087.8ef31560.png)]
🛹 情况五:忽略某些异常
@SentinelResource(value = "add",blockHandler = "fail_add",fallback = "fallback_add",
exceptionsToIgnore = {IllegalArgumentException.class})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fbTAk9FJ-1676296873420)(SpringCloud.assets/image-20220429181851414.ece49582.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEWJiMVv-1676296873421)(SpringCloud.assets/image-20220429181925759.1dd7e434.png)]
🚬 十、OpenFeign调用
pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
yml
#前面也已经添加了 #激活Sentinel对Feign的支持 feign: sentinel: enabled: true
主启动类 @EnableFeignClients
feign接口
import com.ydlclass.consumer.domain.Goods; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "cloudalibaba-sentinal-provider",fallback = GoodsFeignImpl.class) public interface GoodsFeign { @GetMapping("/gooods//findById/{id}") public Goods findById(@PathVariable("id") Integer id); }
实现类PaymentFallbackService
import com.ydlclass.consumer.domain.Goods; import org.springframework.stereotype.Component; @Component public class GoodsFeignImpl implements GoodsFeign{ @Override public Goods findById(Integer id) { Goods goods =new Goods(); goods.setGoodId(-3); goods.setPrice(-3); goods.setStock(-3); goods.setTitle("feign出错之后的特殊对象"); return goods; } }
controller
/** * 使用OpenFeign调用 */ @Autowired private GoodsFeign goodsFeign; @GetMapping("/add1/{id}") public Goods add1(@PathVariable("id")Integer id){ Goods goods = goodsFeign.findById(id); return goods; }
测试出错,直接停了provider
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFhPzxfV-1676296873421)(SpringCloud.assets/image-20220429183335192.ae216a5f.png)]
🚬 十一、配置持久化
sentinel的流控配置是临时的,所以我们可以把配置持久化到nacos
pom
<!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
yml
sentinel: # 将 sentinel 中的配置文件数据存到 Nacos 中 datasource: ds1: nacos: server-addr: localhost:7777 #nacos dataId: ${spring.application.name} # 项目名 groupId: DEFAULT_GROUP # 默认组 data-type: json # 类型 json rule-type: flow # 流量规则 flow
nacos添加配置
[ { "resource": "/order/add1/{id}", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
- resource:资源名称
- limitApp:来源应用
- grade:阈值类型,0表示线程数,1表示QPS
- count:单机阈值
- strategy:流控模式,0表示直接,1表示关联,2表示链路
- controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
- clusterMode:是否集群
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dv8DrbOF-1676296873421)(SpringCloud.assets/image-20230204223601866.png)]
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWd0L2xw-1676296873422)(SpringCloud.assets/image-20220429185954032.bde212b1.png)]