目录
学习SpringCloud指南 ☆ ☆ ☆ ☆ ☆
小白学习SpringCloud 使用与Nacos
小白学习SpringCloud 远程通信【OpenFeign】
小白学习SpringCloud 配置中心【Nacos_Config】
小白学习SpringCloud 网关【Gateway】
1. 限流
2. Gateway限流的实现
2.1 导入pom依赖
2.2 添加redis配置
2.3 添加限流配置
2.4 RequestRateLimiterConfig 配置类
2.5 整合yml文件参考
3. JMeter压力测试
4. 熔断
4.1 添加熔断配置
4.2 整合yml文件参考
4.3 服务器降级响应处理
限流的目的是通过对并发访问/请求进行限速或者对一个时间窗口内的请求进行限速来保护系统,一旦达 到限制速率则可由拒绝服务,就是定向到错误页或友好的展示页,排队或等待。
限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击。在高并发的应用中,限流是 一个绕不开的话题。
令牌桶算法
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则 需要先从桶 里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
- QPS 每秒请求数,就是说服务器在一秒的时间内处理了多少个请求。
提高带宽
4.0.0
com.jmh
nacos_gateway
0.0.1-SNAPSHOT
nacos_gateway
Demo project for Spring Boot
UTF-8
1.8
1.8
2.3.7.RELEASE
Hoxton.SR5
2.1.1.RELEASE
org.springframework.boot
spring-boot-starter-test
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-loadbalancer
ma.glasnost.orika
orika-core
1.4.6
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-webflux
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.boot
spring-boot-starter-actuator
io.projectreactor
reactor-test
test
com.alibaba
fastjson
1.2.35
org.springframework.boot
spring-boot-starter-data-redis-reactive
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
redis:
host: 127.0.0.1
port: 6379
# password: root123
database: 0
filters:
- name: RequestRateLimiter
args:
#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象
key-resolver: '#{@ipAddrKeyResolver}'
#令牌桶填充速率,允许用户每秒处理多少个请求
redis-rate-limiter.replenishRate: 10
#令牌桶总容量,允许在一秒钟内完成的最大请求数
redis-rate-limiter.burstCapacity: 20
package com.jmh.nacos_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());
}
}
server:
port: 8084
spring:
application:
name: nacos-gateway
redis:
host: 127.0.0.1
port: 6379
password: 1234
database: 0
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
#为true代表开启基于服务发现的路由规则。
enabled: false
#配置之后访问时service-id无需大写
lower-case-service-id: true
routes:
# 路由标识(id:标识,具有唯一性)
- id: user-consumer-api
#目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
uri: lb://nacos-consumer
#优先级,越小越优先
#order: 999
#路由条件(predicates:断言)
predicates:
# 路径匹配,
- Path=/aa/**
filters:
#路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
#前缀过滤,请求地址:http://localhost:8084/usr/hello
#此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
#因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
- StripPrefix=1
#限流
- name: RequestRateLimiter
args:
#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象
key-resolver: '#{@ipAddrKeyResolver}'
#令牌桶填充速率,允许用户每秒处理多少个请求
redis-rate-limiter.replenishRate: 10
#令牌桶总容量,允许在一秒钟内完成的最大请求数
redis-rate-limiter.burstCapacity: 20
# # 路由标识(id:标识,具有唯一性)
# - id: user-provider-api
# #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
# uri: lb://nacos-provider
# #优先级,越小越优先
# #order: 999
# #路由条件(predicates:断言)
# predicates:
# # 路径匹配,
# - Path=/bb/**
# filters:
# #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
# #前缀过滤,请求地址:http://localhost:8084/usr/hello
# #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
# #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
# - StripPrefix=1
#自定义动态路由配置
gateway:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
# namespace: xxx-xx-xx-xx
data-id: gateway.json
group: DEFAULT_GROUP
压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中 的瓶颈问 题,减少发布到生产环境后出问题的几率 预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤
在分布式系统中,网关作为流量的入口,大量请求进入网关,向后端远程系统或服务发起调用, 后端服务不可避免的会产生调用失败(超时或者异常),失败时不能让请求堆积在网关上,需要快速失 败并返回回去, 这就需要在网关上做熔断、降级操作。
filters:
- name: Hystrix
args:
name: fallback
fallbackUri: forward:/fallback
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 300
server:
port: 8084
spring:
application:
name: nacos-gateway
redis:
host: 127.0.0.1
port: 6379
password: 1234
database: 0
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
#为true代表开启基于服务发现的路由规则。
enabled: false
#配置之后访问时service-id无需大写
lower-case-service-id: true
routes:
# 路由标识(id:标识,具有唯一性)
- id: user-consumer-api
#目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
uri: lb://nacos-consumer
#优先级,越小越优先
#order: 999
#路由条件(predicates:断言)
predicates:
# 路径匹配,
- Path=/aa/**
filters:
#路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
#前缀过滤,请求地址:http://localhost:8084/usr/hello
#此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
#因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
- StripPrefix=1
#限流
- name: RequestRateLimiter
args:
#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象
key-resolver: '#{@ipAddrKeyResolver}'
#令牌桶填充速率,允许用户每秒处理多少个请求
redis-rate-limiter.replenishRate: 10
#令牌桶总容量,允许在一秒钟内完成的最大请求数
redis-rate-limiter.burstCapacity: 20
#熔断
- name: Hystrix
args:
name: fallback
#降级时返回的路径
fallbackUri: forward:/fallback
# # 路由标识(id:标识,具有唯一性)
# - id: user-provider-api
# #目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
# uri: lb://nacos-provider
# #优先级,越小越优先
# #order: 999
# #路由条件(predicates:断言)
# predicates:
# # 路径匹配,
# - Path=/bb/**
# filters:
# #路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
# #前缀过滤,请求地址:http://localhost:8084/usr/hello
# #此处配置去掉1个路径前缀,再配置上面的 Path=/usr/**,就将**转发到指定的微服务
# #因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
# - StripPrefix=1
#自定义动态路由配置
gateway:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
# namespace: xxx-xx-xx-xx
data-id: gateway.json
group: DEFAULT_GROUP
package com.jmh.nacos_gateway.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author 蒋明辉
* @data 2022/11/9 18:01
*/
@RestController
public class HystrixController {
@RequestMapping("/fallback")
public Object fallback(){
Map map=new HashMap();
map.put("code","204");
map.put("msg","服务降级了");
return map;
}
}