一.Nacos
官方文档: https://nacos.io/zh-cn/docs/what-is-nacos.html
1.1.搭建基础微服务框架
1.总项目依赖版本控制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.eccom</groupId>
<artifactId>springcloud-alibaba-study</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>Common-utils</module>
<module>springcloud-provider-8910</module>
<module>springcloud-consumer-8920</module>
</modules>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<junit.version>4.13</junit.version>
<lombok.version>1.18.20</lombok.version>
<log4j.version>1.2.16</log4j.version>
<springboot.version>2.2.1.RELEASE</springboot.version>
<swagger.version>3.0.0</swagger.version>
<cloud-alibaba.version>0.2.2.RELEASE</cloud-alibaba.version>
<mybatis-plus.version>3.3.0</mybatis-plus.version>
</properties>
<dependencyManagement>
<dependencies>
<!--Spring Cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringBoot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<!--SpringBoot启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--日志工具log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.公共模块版本控制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-alibaba-study</artifactId>
<groupId>com.eccom</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Common-utils</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.2</version>
</dependency>
</dependencies>
</project>
3.服务端版本控制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-alibaba-study</artifactId>
<groupId>com.eccom</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-8910</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.eccom</groupId>
<artifactId>Common-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--应用服务器,类似于tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</project>
4.消费者端版本控制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-alibaba-study</artifactId>
<groupId>com.eccom</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-8920</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.eccom</groupId>
<artifactId>Common-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</project>
1.2.实现配置下发
在nacos里面增加一个配置文件 provider.yaml
provider.yaml
spring:
application:
name: springcloud-provider-8910
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.106.185.202:3310/springcloud_study?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 8910
#配置mapper xml文件的路径
mybatis-plus:
mapper-locations: classpath:com/eccom/mapper/xml/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
自动读取配置的核心包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
在本地配置全局配置文件bootstrap.yaml
在服务启动时,就会去nacos注册中心读取 DataId为 provider.yaml 默认分类的文件
spring:
cloud:
nacos:
config:
file-extension: yaml
server-addr: 127.0.0.1:8848
name: provider
1.3.服务注册
核心依赖 注意带上上面的springcloud和springcloudalibaba版本
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
配置文件
配置服务注册的地址, 服务名称为spring.application.name 有默认分组
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
在启动类上,配置服务注册 @EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = {"com.eccom.mapper"})
public class ProviderApplication8910 {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication8910.class,args);
}
}
启动之后,可以在nacos中看到注册的服务
1.4.服务发现
1.使用RestTemplate
依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
在消费者服务中, 启动类需要加上注解 @EnableDiscoveryClient把服务注册到Nacos中
编写BeanConfig, 把RestTemplate注册到Spring中, 同时带上默认的负载均衡@LoadBalanced
@Configuration
public class BeanConfig {
@Bean
@LoadBalanced //配置负载均衡Ribbon 默认使用轮询RoundRobinRule
public org.springframework.web.client.RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
编写测试Controller, 测试使用RestTemplate能否直接调用到生产者的服务
@RestController
public class TestRestController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/dept/getById/{id}", method = RequestMethod.GET)
public ResponseResult echo(@PathVariable Long id) {
return restTemplate.getForObject("http://springcloud-provider-8910/dept/getById/" + id, ResponseResult.class);
}
}
测试
2.使用feign
在上面的配置文件中,加上一下一个依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
编写要远程调用的接口及其实现类
@FeignClient(name = "springcloud-provider-8910", fallback = ProviderFeignClient.class)
@Component
public interface ProviderClient {
@GetMapping("/dept/getById/{id}")
ResponseResult<DeptInfo> getById(@PathVariable("id") Long id);
}
public class ProviderFeignClient implements ProviderClient{
@Override
public ResponseResult<DeptInfo> getById(Long id) {
return null;
}
}
在启动类上加上注解@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication8920 {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication8920.class, args);
}
}
编写controller
@RestController
@Api(tags = "consumer控制类")
@RequestMapping("/dept")
public class ConsumerController {
@Autowired
private ProviderClient providerClient;
@GetMapping("/getByIdFeign/{id}")
public ResponseResult<DeptInfo> getDeptInfoFeign(@PathVariable("id") Long id){
ResponseResult<DeptInfo> result = providerClient.getById(id);
return ResponseResult.buildResponseResult(ResCodeEnum.SUCCESS,result.getData());
}
}
测试
二.Sentinel
sentinel-core
Sentinel 核心模块,实现限流、熔断等基本能力。
sentinel-dashboard
Sentinel 可视化控制台,提供基本的管理界面,配置限流、熔断规则等,展示监控数据等。
sentinel-adapter
Sentinel 适配,Sentinel-core 模块提供的是限流等基本API,主要是提供给应用自己去显示调用,对代码有侵入性,故该模块对主流框架进行了适配,目前已适配的模块如下:sentinel-apache-dubbo-adapter 对 Apache Dubbo 版本进行适配,这样应用只需引入 sentinel-apache-dubbo-adapter 包即可对 dubbo 服务进行流控与熔断,大家可以思考会利用 Dubbo 的哪个功能特性。 sentinel-dubbo-adapter 对 Alibaba Dubbo 版本进行适配。 sentinel-grpc-adapter 对 GRPC 进行适配。 sentinel-spring-webflux-adapter 对响应式编程框架 webflux 进行适配。 sentinel-web-servlet 对 servlet 进行适配,例如 Spring MVC。 sentinel-zuul-adapter 对 zuul 网关进行适配。
sentinel-cluster
提供集群模式的限流与熔断支持,因为通常一个应用会部署在多台机器上组成应用集群。
sentinel-transport
网络通讯模块,提供 Sentinel 节点与 sentinel-dashboard 的通讯支持,主要有如下两种实现。sentinel-transport-netty-http 基于 Netty 实现的 http 通讯模式。 sentinel-transport-simple-http 简单的 http 实现方式。
sentinel-extension
Sentinel 扩展模式。主要提供了如下扩展(高级)功能:sentinel-annotation-aspectj 提供基于注解的方式来定义资源等。 sentinel-parameter-flow-control 提供基于参数的限流(热点限流)。 sentinel-datasource-extension 限流规则、熔断规则的存储实现,默认是存储在内存中。 sentinel-datasource-apollo 基于 apollo 配置中心实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-consul 基于 consul 实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-etcd 基于 etcd 实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-nacos 基于 nacos 实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-redis 基于 redis 实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-spring-cloud-config 基于 spring-cloud-config 实现限流规则、熔断规则的存储,动态推送生效机制。 sentinel-datasource-zookeeper 基于 zookeeper 实现限流规则、熔断规则的存储,动态推送生效机制。
2.1.Sentinel是什么
Sentinel: 分布式系统的流量防卫兵
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
- 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel 分为两个部分
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
2.2.项目组建
1.服务端依赖
这里引用的是spring-cloud-starter-alibaba-sentinel 2.2.0RELEASE版本
这个版本里面的包都是1.5.2版本,无法与项目要求对应, 因此全部替换为1.7.2版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-alibaba-study</artifactId>
<groupId>com.eccom</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-8910</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.eccom</groupId>
<artifactId>Common-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--应用服务器,类似于tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-server-default</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</exclusion>
<exclusion>
<artifactId>sentinel-cluster-common-default</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
<exclusion>
<artifactId>sentinel-cluster-client-default</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
<exclusion>
<artifactId>sentinel-transport-simple-http</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-client-default</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<artifactId>sentinel-core</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-cluster-server-default</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<artifactId>sentinel-core</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
<exclusion>
<artifactId>sentinel-parameter-flow-control</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</exclusion>
<exclusion>
<artifactId>sentinel-datasource-extension</artifactId>
<groupId>com.alibaba.csp</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
2.服务端注册资源
注册资源并且开启限流与异常处理办法
在接口实现类上面绑定限流降级 和 异常处理方法
@Service
public class DeptInfoServiceImpl extends ServiceImpl<DeptInfoMapper, DeptInfo> implements DeptInfoService {
/**
* @Author DaiBowen
* @Description 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 TestGetById 表示资源名。
* @Date 2021/11/19 15:26
* @Param [id]
*/
@SentinelResource(value = "TestGetById",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handleFlowQpsException",
fallbackClass = CustomerFallbackHandler.class,
fallback = "testGetByIdFallback")
@Override
public DeptInfo getDeptInfoById(Long id) {
if (id == 10L) {
System.out.println(10);
throw new RuntimeException();
}
return baseMapper.selectById(id);
}
@SentinelResource(value = "getAll",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handleFlowQpsException1",
fallbackClass = CustomerFallbackHandler.class,
fallback = "testGetByIdFallback1")
@Override
public List<DeptInfo> getAll() {
return baseMapper.selectList(null);
}
}
自定义异常 和 限流降级处理类
public class CustomerBlockHandler {
/**
* @Author DaiBowen
* @Description 注意1:返回值类型必须与业务方法的返回值类型相同
* 注意2:参数必须有业务方法参数,且最后增加一个 BlockException e
* 注意3:此方法必须是static
* @Date 2021/11/19 15:28
* @Param [id, e]
*/
public static DeptInfo handleFlowQpsException(Long id, BlockException e) {
e.printStackTrace();
return new DeptInfo().setDeptName("限流或者降级了");
}
public static List<DeptInfo> handleFlowQpsException1(BlockException e) {
e.printStackTrace();
return new ArrayList<DeptInfo>();
}
}
public class CustomerFallbackHandler {
public static DeptInfo testGetByIdFallback(Long id, Throwable e) {
return new DeptInfo().setDeptName("出现异常啦");
}
public static DeptInfo testGetByIdFallback1(Throwable e) {
return new DeptInfo().setDeptName("出现异常啦");
}
}
3.通过浏览器访问接口
可以去控制台设置相关策略
2.3.流量控制
官方文档: https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
流量控制(flow control): 监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
限流的直接表现是在执行
Entry nodeA = SphU.entry(resourceName)
的时候抛出FlowException
异常。FlowException
是BlockException
的子类,您可以捕捉BlockException
来自定义被限流之后的处理逻辑。这一块在代码中有所体现
当我在dashboard中, 设置当前 “TestGetById”资源的每秒阈值为1时,如图:
此时,当我持续刷新访问这个资源,就会跳出以下结果
控制台
流量控制主要有两种统计类型:
一种是统计并发线程数,另外一种则是统计 QPS。类型由
FlowRule
的grade
字段来定义。其中,0 代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制。其中线程数、QPS 值,都是由StatisticSlot
实时统计获取的。
2.4.熔断降级
官方文档:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
1.熔断策略
- 慢调用比例 (
SLOW_REQUEST_RATIO
):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。 - 异常比例 (
ERROR_RATIO
):当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0, 1.0]
,代表 0% - 100%。 - 异常数 (
ERROR_COUNT
):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
2.测试
在dashboard中,设置当前的 TestGetById资源的 降级规则如下
此时, 多次手动制造异常, 快速刷新, 当2s内出啊先5次异常时, 就会出现和限流一样的效果, 如下:
3.熔断降级规则说明
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即规则的作用对象 | |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为 s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
2.5.热点参数限流
官方文档: 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.概述
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
热点参数限流的依赖
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-parameter-flow-control</artifactId> <version>1.7.1</version> </dependency>
dashboard中,设置要热点限制的规则
这里代表 2s内该resource 的第一个参数可以通过10次请求, 超过10次就会被限流
参数例外项: 当这个参数的值为long类型的1时, 只要2s内有超过一次请求, 就会被限流
2.6.sentinel配置持久化到nacos
多种类型策略如何配置 https://www.cnblogs.com/FlyGoldfish/articles/14269884.html
1.引入依赖
这里要结合项目依赖, 因为有版本冲突问题, 所以排掉了两个低版本的依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.1</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</exclusion>
</exclusions>
</dependency>
2.限流
项目中application.yml
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: 127.0.0.1:8080
eager: true
datasource:
ds:
nacos:
server-addr: localhost:8848
data-id: sentinel-flow
group-id: DEFAULT_GROUP #默认分组
data-type: json #配置类型为json
rule-type: flow #限流
# 要从nacos中拿到的配置
# [
# {
# "resource": "TestGetById",
# "limitApp": "default",
# "grade": 0, # 0是线程 1是QPS
# "count": 2, # 阈值数
# "strategy": 0, #调用关系限流策略
# "controlBehavior": 0, #流量控制效果(直接拒绝、Warm Up、匀速排队)
# "clusterMode": false
# }
# ]
nacos配置中心的配置
这个时候,项目启动就会去nacos注册中心中拿取对应的配置读到项目中
当配置中心的配置文件发生改动时, 会自动把改动同步到项目中
这是由nacos-config做到的 详见 一.1.2配置下发
在这里读取到的有关限流的配置, 会在项目启动后, 自动导入到dashboard中可视化查看
限流配置参数详解
- resource:资源名,即限流规则的作用对象
- count:限流阈值
- 0:并发线程数
- 1:QPS
- grade:限流阈值类型
- limitApp:流控针对的调用来源,若为 default 则不区分调用来源
- strategy:调用关系限流策略
- 0: STRATEGY_DIRECT
- 根据调用方进行限流。ContextUtil.enter(resourceName, origin) 方法中的 origin 参数标明了调用方的身份。
- 如果 strategy 选择了DIRECT ,则还需要根据限流规则中的 limitApp 字段根据调用方在不同的场景中进行流量控制,包括有:”所有调用方“、”特定调用方origin“、”除特定调用方origin之外的调用方“。
- 1: STRATEGY_RELATE
- 根据关联流量限流。当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联,可使用关联限流来避免具有关联关系的资源之间过度的争抢。
- 比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。
- 举例来说:read_db 和 write_db 这两个资源分别代表数据库读写,我们可以给 read_db 设置限流规则来达到写优先的目的:设置 FlowRule.strategy 为 RuleConstant.STRATEGY_RELATE,同时设置 FlowRule.refResource 为 write_db。这样当写库操作过于频繁时,读数据的请求会被限流。
- 2: STRATEGY_CHAIN
- 根据调用链路入口限流。假设来自入口 Entrance1 和 Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许根据某个入口的统计信息对资源进行限流。
- 举例来说:我们可以设置 FlowRule.strategy 为 RuleConstant.CHAIN,同时设置 FlowRule.refResource 为 Entrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而对来自 Entrance2 的调用可以放行。
- 0: STRATEGY_DIRECT
- controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
- 0: CONTROL_BEHAVIOR_DEFAULT
- 这种方式是:直接拒绝,该方式是默认的流量控制方式,当 qps 超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。
- 这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位。
- 1: CONTROL_BEHAVIOR_WARM_UP
- 这种方式是:排队等待 ,又称为 冷启动。该方式主要用于当系统长期处于低水位的情况下,流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。
- 通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮的情况。
- 2.CONTROL_BEHAVIOR_RATE_LIMITER
- 这种方式是:慢启动,又称为 匀速器模式。这种方式严格控制了请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
- 这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
- 0: CONTROL_BEHAVIOR_DEFAULT
- clusterMode:是否集群
- true
- false
3.熔断降级
配置本地配置文件
在nacos中编写要下发的配置文件
在dashboard中,可以查看到, 配置文件已经同步
参数详解
见https://blog.csdn.net/yuanchangliang/article/details/111663821?ops_request_misc=&request_id=&biz_id=102&utm_term=sentinel%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%86%94%E6%96%AD&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-111663821.pc_search_result_control_group&spm=1018.2226.3001.4187
第五点
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即规则的作用对象 | |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为 s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
- grade
- 0: 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,
对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位)
,那么在接下的时间窗口(DegradeRule 中的timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意Sentinel 默认统计的 RT 上限是 4900 ms
,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx
来配置。 - 1:异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的
每秒请求量 >= N(可配置)
,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)
之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。 - 2:异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源
近 1 分钟的异常数目超过阈值之后会进行熔断
。注意由于统计时间窗口是分钟
级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
- 0: 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,
2.7.系统自适应限流
之前的配置操作,采取的是针对**单个请求地址
、请求别名
进行配置的限流操作,sentinel同时也提供了一种很潮流的方式实现配置操作–—系统自适应限流
**。
什么是是自适应限流
Sentinel 系统自适应限流从
整体维度
对应用入口流量进行控制,结合应用的 Load
、CPU 使用率
、总体平均 RT
、入口 QPS
和并发线程数
等几个维度的监控指标,通过自适应
的流控策略,让系统的入口流量
和系统的负载
达到一个平衡
,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
-
Load 自适应(
仅支持Linux/Unix-like
)
系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。(系统核心数*2.5
) -
CPU usage(
1.5.0+ 版本
)
当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。 -
平均 RT
当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒
。 -
并发线程数
当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。 -
入口 QPS
当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。