SpringCloud 服务限流与熔断
创始人
2024-04-05 23:49:17
0

目录

学习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 服务器降级响应处理


学习SpringCloud指南 ☆ ☆ ☆ ☆ ☆

  小白学习SpringCloud 使用与Nacos

  小白学习SpringCloud 远程通信【OpenFeign】

  小白学习SpringCloud 配置中心【Nacos_Config】

  小白学习SpringCloud 网关【Gateway】


问题分析 

     “一码通”一度瘫痪,西安电信遭质疑!崩溃原因到底是什么?_腾讯新闻 

      从技术角度分析一下,西安一码通为何反复崩溃? - 知乎  

 主要问题

  •  限流问题:市民在长时间无法刷出健康码的情况下,多次退出刷新重试,新的流量到达服务   器,导 致服务器压力变大、承受负载增加,说明“西安一码通”系统没有做好限流措施。 

  •  服务器问题:无论是企业和个人在租用服务器的时候都会受到峰值承受限制的,一旦超过服   务器的 承受能力,就会导致服务器瘫痪,应用程序暂停,网站无法访问。服务器是有峰值限   制的,不可能 承受无上限的并发能力。而造成服务器瘫痪的原因就是在同一段时间内,访问   人数多,造成高流量 的突进,超出了服务器的承受范围。

  •  架构问题:“西安一码通”功能影响“核酸检测”服务,说明模块间从界面到数据调用互相影响,   可能 不是微服务架构。 

  •  性能过载:典型的性能过载场景,不论内部根因是数据库瓶颈点,还是网络链接数瓶颈点等   等,外 因都是因为过载导致。 

  •  设计漏洞:没有考虑高流量高负载的情况,导致测试不充分;产品设计未考虑千万级的并发   访问, 交付前未进行同等级的压力测试。 

  •  压力测试:在市民长时间无法看到健康码的情况下,多次退出刷新重试,新的流量到达服务   器,导 致服务器压力变大、承受负载增加。说明压力测试不够。 

1. 限流

限流的目的是通过对并发访问/请求进行限速或者对一个时间窗口内的请求进行限速来保护系统,一旦达 到限制速率则可由拒绝服务,就是定向到错误页或友好的展示页,排队或等待。

限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击。在高并发的应用中,限流是 一个绕不开的话题。

 

令牌桶算法

 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则   需要先从桶 里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

  •  QPS 每秒请求数,就是说服务器在一秒的时间内处理了多少个请求。

提高带宽

 

2. Gateway限流的实现

    2.1 导入pom依赖


4.0.0com.jmhnacos_gateway0.0.1-SNAPSHOTnacos_gatewayDemo project for Spring BootUTF-81.81.82.3.7.RELEASEHoxton.SR52.1.1.RELEASEorg.springframework.bootspring-boot-starter-testcom.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.cloudspring-cloud-starter-openfeignorg.springframework.cloudspring-cloud-loadbalancerma.glasnost.orikaorika-core1.4.6org.projectlomboklombokorg.springframework.bootspring-boot-starter-webfluxorg.springframework.cloudspring-cloud-starter-gatewayorg.springframework.bootspring-boot-starter-actuatorio.projectreactorreactor-testtestcom.alibabafastjson1.2.35org.springframework.bootspring-boot-starter-data-redis-reactiveorg.springframework.cloudspring-cloud-starter-netflix-hystrixorg.springframework.bootspring-boot-dependencies${spring-boot.version}pomimportorg.springframework.cloudspring-cloud-dependencies${spring-cloud.version}pomimportcom.alibaba.cloudspring-cloud-alibaba-dependencies${spring-cloud-alibaba.version}pomimportorg.springframework.bootspring-boot-maven-plugin
  • Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory类,使用redis和lua脚本 来实现令牌桶的方式。
  • Gateway通过内置的RequestRateLimiter过滤器实现限流,使用令牌桶算法,借助Redis保存中间数 据。用户可通过自定义KeyResolver设置限流维度。
  • 对请求的目标URL进行限流
  • 对来源IP进行限流
  • 特定用户进行限流

   2.2 添加redis配置

redis:host: 127.0.0.1port: 6379# password: root123database: 0
  • 如果redis连接失败,限流功能将不能开启。因为没有redis作为容器来保存令牌,限流功能自  然就失效 了。
  • 可以将redis的配置信息保存到nacos中,通过添加nacos配置中心客户端的方式进行读取

   2.3 添加限流配置

filters:- name: RequestRateLimiterargs:#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象key-resolver: '#{@ipAddrKeyResolver}'#令牌桶填充速率,允许用户每秒处理多少个请求redis-rate-limiter.replenishRate: 10#令牌桶总容量,允许在一秒钟内完成的最大请求数redis-rate-limiter.burstCapacity: 20

  2.4 RequestRateLimiterConfig 配置类

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@Primarypublic KeyResolver ipAddrKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());}/*** 按用户限流*/@BeanKeyResolver userKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));}/*** 按URL限流,即以每秒内请求数按URL分组统计,超出限流的url请求都将返回429状态** @return*/@BeanKeyResolver apiKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getPath().toString());}}

  2.5 整合yml文件参考

server:port: 8084
spring:application:name: nacos-gatewayredis:host: 127.0.0.1port: 6379password: 1234database: 0cloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false#为true代表开启基于服务发现的路由规则。enabled: false#配置之后访问时service-id无需大写lower-case-service-id: trueroutes:# 路由标识(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: RequestRateLimiterargs:#用于限流的键的解析器的 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-xxdata-id: gateway.jsongroup: DEFAULT_GROUP

3. JMeter压力测试

压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中 的瓶颈问 题,减少发布到生产环境后出问题的几率 预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤

4. 熔断

在分布式系统中,网关作为流量的入口,大量请求进入网关,向后端远程系统或服务发起调用, 后端服务不可避免的会产生调用失败(超时或者异常),失败时不能让请求堆积在网关上,需要快速失 败并返回回去, 这就需要在网关上做熔断、降级操作。 

   4.1 添加熔断配置 

filters:- name: Hystrixargs:name: fallbackfallbackUri: forward:/fallback
hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 300

   4.2 整合yml文件参考

server:port: 8084
spring:application:name: nacos-gatewayredis:host: 127.0.0.1port: 6379password: 1234database: 0cloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false#为true代表开启基于服务发现的路由规则。enabled: false#配置之后访问时service-id无需大写lower-case-service-id: trueroutes:# 路由标识(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: RequestRateLimiterargs:#用于限流的键的解析器的 Bean 对象的名字,使用 SpEL表达式根据#{@beanName}获取Bean对象key-resolver: '#{@ipAddrKeyResolver}'#令牌桶填充速率,允许用户每秒处理多少个请求redis-rate-limiter.replenishRate: 10#令牌桶总容量,允许在一秒钟内完成的最大请求数redis-rate-limiter.burstCapacity: 20#熔断- name: Hystrixargs: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-xxdata-id: gateway.jsongroup: DEFAULT_GROUP

    4.3 服务器降级响应处理

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;}}
  •  sentinel (史上最全+入门教程) - 疯狂创客圈 - 博客园

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...