Spring Cloud微服务安全实战_4-10_用spring-cloud-zuul-ratelimit做限流

本篇讲网关上的限流

用开源项目spring-cloud-zuul-ratelimit 做网关上的限流 (项目github:https://github.com/marcosbarbero/

1,在网关项目里,引入限流组件的maven依赖:

2,在网关项目yml配置里,配限流相关配置

github也有相关配置说明:https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit

限流框架限流需要存一些信息,可以存在数据库里,也可以存在redis里,这里就用redis做实验,而且我看该组件的限流存储枚举类里,如果使用数据库保存限流信息,只能用JPA,不能用mybatis(可能歪果仁更喜欢JPA):

public enum RateLimitRepository {
    REDIS,
    CONSUL,
    JPA,
    BUCKET4J_JCACHE,
    BUCKET4J_HAZELCAST,
    BUCKET4J_IGNITE,
    BUCKET4J_INFINISPAN,
}

限流yml配置:

限流的信息,在redis是有有效期的,过了有效期会自动清除,所以要想在redis看到限流的相关信息,这里时间窗口就设置为 10 秒(刚开始我设置的是1秒,redis死活看不到限流信息,浪费了十几分钟时间)

zuul:
  routes: #路由的配置是个Map,可以配置多个
    token:  #token结尾的请求,都转发到http://localhost:9090认证服务器地址
      url:  http://localhost:9090
    order:  #order结尾的请求,都转发到http://localhost:9060 顶单服务
      url:  http://localhost:9060
  sensitive-headers:  null  #设置敏感头设置为空,Authorization等请求头的请求,都往后转发
  ratelimit:
      key-prefix: rate
      enabled: true
      repository: REDIS
      default-policy-list:
        #    ########### 如下的配置就是说:每1秒内不能超过2个请求,2个请求时间加起来不能超过1秒(quota)############
        - limit: 2 #optional - request number limit per refresh interval window
          quota: 1 #optional - request time limit per refresh interval window (in seconds)
          refresh-interval: 10 #时间窗口 (in seconds)
          type: ##根据什么控制流量,可以组合使用,如url、httpmethod组合,就会把 /orders的get和post请求分开处理
            - url
            - http_method
          #- user  #根据用户控制需要Security支持,(一般不用)
          #- origin #根据客户端的ip控制

3,实验

1,分别启动 订单 、认证、网关 三个服务

2,从网关获取一个token:

OAuth2 password模式参数

网关client的username,password

3,拿token访问网关创建订单

手速点的快点,Http就会返回 429 状态码,表示过多的请求。

看redis,已经有限流的信息了:

生成的限流的key是: rate:order:/orders:POST        rate是配置的限流信息的前缀,order是zuul转发的规则,/orders:POST 是配置的限流类型 url 和http_method的组合

当下一个请求过来的时候就会计算key,然后根据key去redis找,看当前的key已经过了多少个请求了,来判断这次请求能不能过。

大部分情况下,根据user 、origin、 url 、http_method已经满足需求了。有些特殊的场景,需要根据传过来的参数进行限流,比如有两种优惠券A、B,优惠券A业务简单,每秒能处理100个请求,优惠券B复杂,每秒能处理10个请求,此时自带的限流规则就不能满足需求了。限流归根揭底是根据key来限流的,所以此时就要自定义key的生成规则。

自定义key的生成规则:

import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitUtils;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.DefaultRateLimitKeyGenerator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义限流key生成规则,自定义限流规则
 */
@Component
public class MyKeyGen extends DefaultRateLimitKeyGenerator {

    public MyKeyGen(RateLimitProperties properties, RateLimitUtils rateLimitUtils){
        super(properties,rateLimitUtils);
    }

    @Override
    public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy) {
        //可以从route拿出路由信息,自定义key生成规则:https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit#usage
        return super.key(request, route, policy);
    }
}

重写错误处理:

package com.nb.security.filter;

import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.DefaultRateLimiterErrorHandler;
import org.springframework.stereotype.Component;

/**
 * 限流错误自定义处理
 */
@Component
public class MyRateLimitErrorHandler extends DefaultRateLimiterErrorHandler {

    //限流数据存时候报错了的处理,一般不覆盖
    @Override
    public void handleSaveError(String key, Exception e) {
        super.handleSaveError(key, e);
    }

    //限流取数据报错的处理,一般不覆盖
    @Override
    public void handleFetchError(String key, Exception e) {
        super.handleFetchError(key, e);
    }

    //限流错误处理,记日志等
    @Override
    public void handleError(String msg, Exception e) {
        super.handleError(msg, e);
    }
}

都在网关上做限流是有问题的

1,耦合

  如上所述的根据不同的优惠券进行的限流,如果优惠券又多了种类型,就要重写网关的限流的代码,重写部署网关,这就是耦合,是不行的。服务和服务之间,以及服务和基础组件之间,一定要解耦。微服务场景下解耦是价值最大的事。一旦两个服务耦合在一块,一个变了,另一个也要跟着变。

2,限流的数量的问题

  网关只能处理从整个微服务外边进来的请求,并不处理微服务之间的调用。如,有A B两个微服务,A还调用了B服务,A、B服务每秒处理的请求最大都是100个,网关限流 A 100请求/秒   ,B 100请求/秒。此时有100个A请求到网关,100个B请求也到了网关,都通过了网关,而此时,100个到A的请求又请求了100次B,导致B服务不可用!

所以:在网关上不要做细粒度的限流,没有用,因为很多服务之间的调用,都不走网关。网关层面只根据硬件设备的处理能力做一些限流,如服务的节点用的是tomcat,根据每个tomcat的资源配置,计算能处理的多少并发请求,根据这个去限流。具体的方法,跟业务逻辑的耦合,都不要发生在网关上的限流逻辑里。这就是上边配置里说的,限流类型 user最好不在网关上用。

本篇github :  https://github.com/lhy1234/springcloud-security/tree/chapt-4-10-ratelimit  如果对你有一点帮助,点个小星星吧!谢谢

原文地址:https://www.cnblogs.com/lihaoyang/p/12127768.html

时间: 2024-10-15 08:05:55

Spring Cloud微服务安全实战_4-10_用spring-cloud-zuul-ratelimit做限流的相关文章

Spring Cloud微服务框架 实战企业级优惠券系统

第1章 课程介绍[终于等到你,快来认识我]本章中将对课程中涉及到的技术.工具.业务等进行简单介绍. 第2章 准备工作[工欲善其事,必先利其器]本章中将对课程中使用到的技术工具做介绍,包括Maven.MySQL.Redis.Kafka:会对它们的功能.安装.基本的使用方法进行介绍. 第3章 SpringBoot 开发框架[基础打不牢,学问攀不高]课程主体业务使用SpringCloud框架开发实现,但是SpringCloud基于SpringBoot实现.为便于更顺畅学习,本章中会对SpringBoo

Spring cloud微服务安全实战

第1章 课程导学我们会对整个课程的内容做一个简要的介绍,包括章节的安排,使用的主要技术栈,实战案例的介绍以及前置知识的介绍等内容. 第2章 环境搭建开发工具的介绍及安装,介绍项目代码结构并搭建,基本的依赖和参数设置. 第3章 API安全我们从简单的API场景入手,讲述API安全相关的知识.首先我们会介绍要保证一个API安全都需要考虑哪些问题,然后我们针对这些问题介绍常见的安全机制,我们会针对每种问题和安全机制编写相应的代码,让大家对这些问题和安全机制有一个初步的认识.... 第4章 微服务网关安

Spring cloud微服务安全实战完整教程

本文配套视频教程及资料获取:点击这里 Spring Cloud微服务安全实战 采用流行的微服务架构开发,应用程序访问安全将会面临更多更复杂的挑战,尤其是开发者最关心的三大问题:认证授权.可用性.可视化.本课程从简单的API安全入手,过渡到复杂的微服务场景,解决上述三大问题痛点,并结合实际给出相应解决方案.帮助大家形成对安全问题的系统性思考,实战开发一套可在中小公司落地的完整的安全方案. 学习目标: 技术要点: 环境参数: 本文配套视频教程及资料获取:点击这里 原文地址:https://www.c

Spring cloud微服务安全实战-6-1本章概述

这一章来讲一下,微服务之间的通讯安全. 当前这个架构还存在的问题 在网关上做限流还是有一些问题的.例如我的订单服务限流是100,库存服务限流也是100.但是我的订单服务会调用我的库存服务.那么在网关这,给订单转100个请求,库存转100个请求,最后订单又调了库存,库存会同时受到200个请求.这时候库存服务可能就挂掉了. 这是在网关这里做限流,可能会出现的一些问题. 第二个问题就是身份认证. 效率低,在网关上每一个请求都要去认证服务器验令牌.这样就会导致多一次网络请求的开销.同时我的认证服务器压力

Spring Cloud微服务安全实战_6-1_微服务之间的通讯安全之概述

到目前为止已经实现了一个基于微服务的,前后端分离(这里我用的jquery做的,并不是真的前后端分离,因为我不会vue和angular所以没用)的架构.在网关上做了限流.认证.审计.授权等安全机制,在前端应用上也做了SSO单点登录, 现在的架构存在的问题是: 1,在网关做限流. 在网关上做限流是有问题的,比如订单服务限流是100,库存服务限流也是100,订单服务又调了库存服务.如果网关上给订单转了100个请求,给库存转了100个请求,订单又调了库存,这时候库存就同时接到了200个请求,库存服务就可

Spring Cloud微服务安全实战_4-5_搭建OAuth2资源服务器

上一篇搭建了一个OAuth2认证服务器,可以生成token,这篇来改造下之前的订单微服务,使其能够认这个token令牌. 本篇针对订单服务要做三件事: 1,要让他知道自己是资源服务器,他知道这件事后,才会在前边加一个过滤器去验令牌(配置@EnableResourceServer 配置类) 2,要让他知道自己是什么资源服务器(配置资源服务器ID) 3,配置去哪里验令牌,怎么验令牌,要带什么信息去验 (配置@EnableWebSecurity 配置TokenServices,配置Authentica

Spring cloud微服务安全实战-4-7重构代码以适应真实环境

现在有了认证服务器,也配置了资源服务器.也根据OAuth协议,基于令牌认证的授权也跑通了.基本的概念也有了简单的理解. 往下深入之前,有几个点,还需要说一下 使用scopes来控制权限,scopes可以理解为之前的ACL 第三章的时候自己写的ACL来控制的读写权限.在OAuth协议里面用scopes来实现ACL的权限控制,两方面,首先在服务器这一端,可以针对不同的应用发出去不同权限的令牌, . 比如针对oderApp可以有读权限,也可以有写的权限. 针对orderService发出去的就只有re

Spring cloud微服务安全实战-5-7实现基于session的SSO(客户端应用的Session有效期)

授权模式改造成了Authorization code完成了改造的同时也实现了SSO.微服务环境下的前后端分离的单点登陆. 把admin的服务重启.刷新页面 并没有让我去登陆,直接就进入了首页. order的API控制台 只要你在认证服务器上的session没过期.认证服务器就知道你是谁,他就不会让你输入用户名密码了.直接跳回到客户端应用. 一共有三个有效期. 退出操作 退出的时候.现在前端服务器清空session,认证服务器也需要清空session 在前端服务器退出后,再跳转到认证服务器执行退出

Spring cloud微服务安全实战-6-2JWT认证之认证服务改造

首先来解决认证的问题. 1.效率低,每次认证都要去认证服务器调一次服务. 2.传递用户身份,在请求头里面, 3.服务之间传递请求头比较麻烦. jwt令牌. spring提供了工具,帮你在微服务之间传递令牌.让你不用去写额外的代码 服务器端的改造 看一下认证服务器配置的这个类.这里有个tokenStore,就是令牌的存储器.现在用的是jdbc的TokenStore,令牌是存在数据库里的 我们new  一个jwtTokenStore它 需要一个参数jwtTokenEnhancer 需要set一个ke