目录
一、限流
1、为什么会出现限流
在我们日常生活中经常出现系统瘫痪问题,从问题中也道出了一个原因就是系统因访问量过大系统崩溃
从中也道出的主要问题:
限流问题、服务器问题、架构问题、性能过载、设计漏洞、压力测试
2、限流的目的
通过对并发访问/请求进行限速或者对一个时间窗口内的请求进行限速来保护系统,一旦达
到限制速率则可由拒绝服务,就是定向到错误页或友好的展示页,排队或等待
3、限流的好处
限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击。在高并发的应用中,限流是一个绕不开的话题
就像上图所示:如果没有交警在现场指挥,车辆来来往往就会形成拥堵,导致道路不畅,就如系统一样,如果一下子访问量太多,系统处理不过来,导致系统瘫痪
4、实现限流的两种方法
1、令牌桶算法
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务
QPS
每秒请求数,就是说服务器在一秒的时间内处理了多少个请求
2、提高带宽
实现带宽,阿里云不同主机的价格,带宽越多,价格越贵
5、Gateway限流的实现
1、导入依赖
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
<spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>
Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory类,使用redis和lua脚本来实现令牌桶的方式。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
整体依赖:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zj</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>gateway</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
<spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.35</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<mainClass>com.zj.gateway.GatewayApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2、添加redis配置
redis:
host: 127.0.0.1
port: 6379
# password: root123
database: 0
如果redis连接失败,限流功能将不能开启。因为没有redis作为容器来保存令牌,限流功能自然就失效了。
可以将redis的配置信息保存到nacos中,通过添加nacos配置中心客户端的方式进行读取
添加限流配置:
filters:
- name: RequestRateLimiter
args:
#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象
key-resolver: '#{@ipAddrKeyResolver}'
#令牌桶填充速率,允许用户每秒处理多少个请求
redis-rate-limiter.replenishRate: 10
#令牌桶总容量,允许在一秒钟内完成的最大请求数
redis-rate-limiter.burstCapacity: 20
3、配置资源类
Gateway通过内置的RequestRateLimiter过滤器实现限流,使用令牌桶算法,借助Redis保存中间数据。用户可通过自定义KeyResolver设置限流维度。
1、对请求的目标URL进行限流
2、对来源IP进行限流
3、特定用户进行限流
RequestRateLimiterConfig:
package com.zj.gateway;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;
/**
* 请求限流配置
*/
@SuppressWarnings("all")
@Configuration
public class RequestRateLimiterConfig {
/**
* 按IP来限流
*/
@Bean
@Primary
public KeyResolver ipAddrKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
/**
* 按用户限流
*/
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
/**
* 按URL限流,即以每秒内请求数按URL分组统计,超出限流的url请求都将返回429状态
*
* @return
*/
@Bean
KeyResolver apiKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getPath().toString());
}
}
4、使用Jmeter进行压力测试
Jmeter详细测试:手把手教你用jmeter做压力测试(详图) - 知乎
压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中的瓶颈问题,减少发布到生产环境后出问题的几率预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤
4.1将压缩文件进行解压,不要解压到c盘
4.2打开Jemter进行测试
4.3进入到jmeter中后需要进行配置
4.3.1点击右键配置线程组
4.3.2配置http请求
4.3.3配置表格观察结果
4.4进行压力测试:
设置访问线程数量,资源文件设置的访问数量是20(上述资源文件有讲到)
全部通过:
如果线程访问数量超出了资源文件中规定的数量,就会显示为红色。
二、熔断
1、熔断的定义
在分布式系统中,网关作为流量的入口,大量请求进入网关,向后端远程系统或服务发起调用,后端服务不可避免的会产生调用失败(超时或者异常),失败时不能让请求堆积在网关上,需要快速失败并返回回去,这就需要在网关上做熔断、降级操作。
2、熔断的操作
1、导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、配置资源文件
filters:
- name: Hystrix
args:
name: fallback
fallbackUri: forward:/fallback
3、写好熔断之后提示的类
Testcontroller:
package com.zj.gateway;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TestController {
@RequestMapping("/fallback")
public Object fallback(){
Map<String,Object> map=new HashMap<>();
map.put("code",204);
map.put("msg","服务已经降级了");
return map;
}
}
4、将服务进行停止来仿造服务崩溃的情景
再次访问时就已经熔断
今天的知识就分享到这了,希望能够帮助到你!