0
点赞
收藏
分享

微信扫一扫

SpringCloud服务限流与熔断

丹柯yx 2022-02-17 阅读 38

(一)Spring Cloud核心组件:Hystrix

在微服务架构里,一个系统会有很多的服务。

以上面的业务场景为例:订单服务在一个业务流程里需要调用三个服务。

现在假设订单服务自己最多只有 100 个线程可以处理请求,然后呢,积分服务不幸的挂了,每次订单服

务调用积分服务的时候,都会卡住几秒钟,然后抛出 个超时异常 出现问题: 微服务架构中的服务雪崩问题

如果系统处于高并发的场景下,大量请求涌过来的时候,订单服务的 100 个线程都会卡在请求积分

服务这块。导致订单服务没有一个线程可以处理请求

然后就会导致别人请求订单服务的时候,发现订单服务也挂了,不响应任何请求了

Hystrix 是隔离、熔断以及降级的一个框架。

比如订单服务请求库存服务是一个线程池,请求仓储服务是一个线程池,请求积分服务是一个线程池。

每个线程池里的线程就仅仅用于请求那个服务。

积分服务挂了

会导致订单服务里的那个用来调用积分服务的线程都卡死不能工作!

但是由于订单服务调用库存服务、仓储服务的这两个线程池都是正常工作的,所以这两个服务不会受到

任何影响。

这个时候如果别人请求订单服务,订单服务还是可以正常调用库存服务扣减库存,调用仓储服务通知发

货。

只不过调用积分服务的时候,每次都会报错。但是如果积分服务都挂了,每次调用都要去卡住几秒钟!

所以我们直接对积分服务熔断不就得了,比如在 5 分钟内请求积分服务直接就返回了,不要去走网络请求

卡住几秒钟,这个过程,就是所谓的熔断!

那人家又说,兄弟,积分服务挂了你就熔断,好歹你干点儿什么啊!别啥都不干就直接返回啊?

没问题,咱们就来个降级:

每次调用积分服务,你就在数据库里记录一条消息,说给某某用户增加了多少积分,因为积分服务挂

了,导致没增加成功!

这样等积分服务恢复了,你可以根据这些记录手工加一下积分。这个过程,就是所谓的降级。

 

(二)问题分析 

主要问题:

限流问题:市民在长时间无法刷出健康码的情况下,多次退出刷新重试,新的流量到达服务器,导

致服务器压力变大、承受负载增加,说明 西安一码通 系统没有做好限流措施。


服务器问题:无论是企业和个人在租用服务器的时候都会受到峰值承受限制的,一旦超过服务器的

承受能力,就会导致服务器瘫痪,应用程序暂停,网站无法访问。服务器是有峰值限制的,不可能

承受无上限的并发能力。而造成服务器瘫痪的原因就是在同一段时间内,访问人数多,造成高流量

的突进,超出了服务器的承受范围。


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

不是微服务架构。


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

因都是因为过载导致。


设计漏洞:没有考虑高流量高负载的情况,导致测试不充分;产品设计未考虑千万级的并发访问,

交付前未进行同等级的压力测试。


压力测试:在市民长时间无法看到健康码的情况下,多次退出刷新重试,新的流量到达服务器,导

致服务器压力变大、承受负载增加。说明压力测试不够。


限流

限流的目的是通过对并发访问 / 请求进行限速或者对一个时间窗口内的请求进行限速来保护系统,一旦达

到限制速率则可由拒绝服务,就是定向到错误页或友好的展示页,排队或等待。

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

一个绕不开的话题。


令牌桶算法 

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶

里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

QPS

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

 

提高带宽 

 

 (三)Gateway限流的实现

1.需要把版本改为2.3.7

Spring Cloud Gateway 官方提供了 RequestRateLimiterGatewayFilterFactory 类,使用 redis lua 脚本

来实现令牌桶的方式。

2.导入redis的依赖

Gateway 通过内置的 RequestRateLimiter 过滤器实现限流,使用令牌桶算法,借助 Redis 保存中间数

据。用户可通过自定义 KeyResolver 设置限流维度。

对请求的目标 URL 进行限流

对来源 IP 进行限流

特定用户进行限流

 3.添加redis配置

注:记得开启你的redis

如果redis连接失败,限流功能将不能开启。因为没有redis作为容器来保存令牌,限流功能自然就失效 了。

可以将redis的配置信息保存到nacos中,通过添加nacos配置中心客户端的方式进行读取

4.导入请求限流的配置类

package com.gateway.code;

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());
    }

}

 5.添加限流的配置

注:在添加限流配置之前把前面写的自定义配置类关掉(把

DynamicRoutingConfig类中的@Component注解注释掉即可

运行效果如下:

 

 

 (四)JMeter压力测试

1.把apache-jmeter-5.2.1.taz解压

 2.进入文件夹点击jmeter.bat直接运行即可

 

 3.点击Options->Choose Language ->Chinese 切换为中文

 4.点击添加线程

 5.点击配置HTTP请求

  

6.点击添加监听器用表格查看结果

 

7.开始进行JMeter压力测试

 

 

 

 (五)熔断

在分布式系统中,网关作为流量的入口,大量请求进入网关,向后端远程系统或服务发起调用,

后端服务不可避免的会产生调用失败(超时或者异常),失败时不能让请求堆积在网关上,需要快速失

败并返回回去,

这就需要在网关上做熔断、降级操作。

1.导入依赖

 2.导入yml配置

3.编写TestController进行熔断测试

package com.gateway.code;

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.关闭生产者启动类进行熔断测试

 开启生产者启动类的效果如下: 

 注:完整版appliaction.yml配置如下:

举报

相关推荐

0 条评论