数据结构与算法简记--剖析微服务接口鉴权限流背后的数据结构和算法

微服务鉴权限流剖析


微服务

  • 把复杂的大应用,解耦拆分成几个小的应用。
  • 有利于团队组织架构的拆分,毕竟团队越大协作的难度越大;
  • 每个应用都可以独立运维,独立扩容,独立上线,各个应用之间互不影响。
  • 有利就有弊:
    • 大应用拆分成微服务之后,服务之间的调用关系变得更复杂,平台的整体复杂熵升高,出错的概率、debug 问题的难度都高了好几个数量级。
  • 为了解决这些问题,服务治理便成了微服务的一个技术重点

服务治理

  • 简单点讲,就是管理微服务,保证平台整体正常、平稳地运行。
  • 涉及的内容:鉴权、限流、降级、熔断、监控告警等等。
  • 服务治理功能的实现,底层依赖大量的数据结构和算法。这里拿其中的鉴权和限流这两个功能,剖析一下实现过程中用到的数据结构和算法。

鉴权

  • 有一个微服务叫用户服务(User Service)。它提供很多用户相关的接口,比如获取用户信息、注册、登录等,给公司内部的其他应用使用。
  • 并不是公司内部所有应用,都可以访问这个用户服务,也并不是每个有访问权限的应用,都可以访问用户服务的所有接口。
  • 需要实现接口鉴权功能
    • 事先将应用对接口的访问权限规则设置好。
    • 当某个应用访问其中一个接口的时候,可以拿应用的请求 URL,在规则中进行匹配。
    • 如果匹配成功,就说明允许访问;
    • 如果没有可以匹配的规则,说明这个应用没有这个接口的访问权限,就拒绝服务。
  • 如何实现快速鉴权
    • 用什么数据结构来存储规则?
    • 用户请求 URL 在规则中快速匹配,用什么的算法?
    • 不同的规则和匹配模式,对应的数据结构和匹配算法也是不一样。
  • 如何实现精确匹配规则
    • 简单规则
    • 不同的应用对应不同的规则集合,可以采用散列表来存储这种对应关系。
    • 每个应用对应的规则集合,该如何存储和匹配?
      • 可以将每个应用对应的权限规则,存储在一个字符串数组中。
      • 当用户请求到来时,拿用户的请求 URL,在这个字符串数组中逐一匹配,匹配的算法就是我们之前学过的字符串匹配算法(比如 KMP、BM、BF 等)
      • 规则不会经常变动,所以,为了加快匹配速度,可以按照字符串的大小给规则排序,把它组织成有序数组这种数据结构。
      • 当要查找某个 URL 能否匹配其中某条规则的时候,可以采用二分查找算法,在有序数组中进行匹配
  • 如何实现前缀匹配规则?
    • 稍微复杂的匹配模式:只要某条规则可以匹配请求 URL 的前缀,这条规则就能够跟这个请求 URL 匹配。
    • Trie 树非常适合用来做前缀匹配
    • 可以将每个用户的规则集合,组织成 Trie 树这种数据结构。
    • Trie 树中的每个节点不是存储单个字符,而是存储接口被“/”分割之后的子目录(比如“/user/name”被分割为“user”“name”两个子目录)。
    • 同样的,规则不会经常变动,所以,在 Trie 树中,可以把每个节点的子节点们,组织成有序数组这种数据结构。
    • 当在匹配的过程中,可以利用二分查找算法,决定从一个节点应该跳到哪一个子节点
  • 如何实现模糊匹配规则?
    • 更加复杂的匹配模式:规则中包含通配符,比如“**”表示匹配任意多个子目录,“*”表示匹配任意一个子目录。只要用户请求 URL 可以跟某条规则模糊匹配,这条规则适用于这个请求。
    • 可以借助正则表达式那个例子的解决思路,来解决这个问题。采用回溯算法,拿请求 URL 跟每条规则逐一进行模糊匹配。
    • 回溯算法复杂度是非常高,如何优化
      • 把不包含通配符的规则和包含通配符的规则分开处理(分治思想)
      • 把不包含通配符的规则,组织成有序数组或者 Trie 树进行精确或前缀匹配(具体组织成什么结构,视具体的需求而定,是精确匹配,就组织成有序数组,是前缀匹配,就组织成 Trie 树)。
      • 剩下的是少数包含通配符的规则,只要把它们简单存储在一个数组中就可以了。尽管匹配起来会比较慢,但是毕竟这种规则比较少,所以这种方法也是可以接受的。
      • 当接收到一个请求 URL 之后,先在不包含通配符的有序数组或者 Trie 树中查找。如果能够匹配,就不需要继续在通配符规则中匹配了;如果不能匹配,就继续在通配符规则中查找匹配。

限流

  • 对接口调用的频率进行限制。比如每秒钟不能超过 100 次调用,超过之后,就拒绝服务。
  • 在很多场景中,发挥着重要的作用。比如在秒杀、大促、双 11、618 等场景中,限流已经成为了保证系统平稳运行的一种标配的技术解决方案
  • 按照不同的限流粒度分类:
    • 每个接口限制不同的访问频率
    • 给所有接口限制总的访问频率
    • 限制某个应用对某个接口的访问频率
  • 如何实现精准限流?
    • 固定时间窗口限流算法:

      • 选定一个时间起点,之后每当有接口请求到来,将计数器加一。
      • 如果在当前时间窗口内,根据限流规则(比如每秒钟最大允许 100 次访问请求),出现累加访问次数超过限流值的情况时,我们就拒绝后续的访问请求。
      • 当进入下一个时间窗口之后,计数器就清零重新计数。
      • 缺点:限流策略过于粗略,无法应对两个时间窗口临界时间内的突发流量
        • 第一个 1s 时间窗口内,100 次接口请求都集中在最后 10ms 内。
        • 第二个 1s 的时间窗口内,100 次接口请求都集中在最开始的 10ms 内。
        • 虽然两个时间窗口内流量都符合限流要求(≤100 个请求),但在两个时间窗口临界的 20ms 内,会集中有 200 次接口请求。
        • 固定时间窗口限流算法并不能对这种情况做限制,所以,集中在这 20ms 内的 200 次请求就有可能压垮系统。
    • 滑动时间窗口限流算法
      • 假设限流的规则是,在任意 1s 内,接口的请求次数都不能大于 K 次。
      • 维护一个大小为 K+1 的循环队列,用来记录 1s 内到来的请求。注意,这里循环队列的大小等于限流次数加一,因为循环队列存储数据时会浪费一个存储单元。
      • 当有新的请求到来时,将与这个新请求的时间间隔超过 1s 的请求,从队列中删除。
      • 再来看循环队列中是否有空闲位置:
        • 如果有,则把新请求存储在队列尾部(tail 指针所指的位置);
        • 如果没有,则说明这 1 秒内的请求次数已经超过了限流值 K,所以这个请求被拒绝服务。
      • 只能在选定的时间粒度上限流,对选定时间粒度内的更加细粒度的访问频率不做限制。
      • 王争限流框架:https://github.com/wangzheng0822/ratelimiter4j

原文地址:https://www.cnblogs.com/wod-Y/p/12219106.html

时间: 2024-11-05 15:55:51

数据结构与算法简记--剖析微服务接口鉴权限流背后的数据结构和算法的相关文章

Spring Cloud微服务接口这么多怎么调试?

前言 今天和大家聊一下Spring Cloud微服务下服务接口调试及管理的话题!我们知道在微服务架构下,软件系统会被拆分成很多个独立运行的服务,而这些服务间需要交互通信,就需要定义各种各样的服务接口.具体来说,在基于Spring Cloud的微服务模式中,各个微服务会基于Spring MVC的Controller定义多个该微服务需要向外部发布的接口. 根据各个微服务功能边界定义的不同,有些微服务会提供与具体业务相关的接口,如支付接口.账户接口等:而有些微服务则会提供一些公共性质的服务接口,如短信

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架.而以下要介绍的正是作者最近两个月的真实项目实践过程,这中间被不少网络Demo示例级别水文误导过,为了以正视听特将实践过程加以总结,希望能够帮到有类似需要的朋友! 一.Sentinel概述 在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素.在并发流量比较高

微服务网关常用限流算法

常用算法有三种:计数器算法.漏斗桶算法.令牌桶算法,市面上最常用的是最后一个 第一个:计数器算法  他维护的是单位时间内的最大请求量,因此极端情况可能造成服务抖动  第二个:漏斗桶算法,这种算法保护了后端的微服务,但是会可能造成微服务网关压力激增 第三种:令牌桶算法 令牌桶算法相对于漏斗桶算法,其实就是少了一个输出速率的设置,他与漏斗桶算法相比,主要是为了保护网关自己,由于网关在实际的应用场景中会显得非常关键,因此大部分的限流算法都会选择令牌桶算法 原文地址:https://www.cnblog

基于微服务API级权限的技术架构

一般而言,企业内部一套成熟的权限系统,都是基于角色(Role)的 访问控制方法(RBAC – Role Based Access Control),即权限 (Permission)与角色相关联,用户(User)通过成为适当角色的成员而得到这 些角色的权限,权限包含资源(或者与操作组合方式相结合),最终实现权限控制 的目的. 背景 权限系统是根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源. 一般而言,企业内部一套成熟的权限系统,都是基于角色(Role)的访问控制方法(

服务接口API限流 Rate Limit

一.场景描述 很多做服务接口的人或多或少的遇到这样的场景,由于业务应用系统的负载能力有限,为了防止非预期的请求对系统压力过大而拖垮业务应用系统,便在对服务接口做了许多策略:服务接口降级.限流.引流等.本文讨论下限流策略,虽然降低了服务接口的访问频率和并发量,却换取服务接口和业务应用系统的可用性. 二.常用的限流算法 常用的限流算法由:楼桶算法和令牌桶算法.本文不具体的详细说明两种算法的原理,原理会在接下来的文章中做说明. 1.漏桶算法 漏桶(Leaky Bucket)算法思路很简单,水(请求)先

JVM+分布式+算法+锁+MQ+微服务+数据库 面试题

JAVA基础 1.JAVA中的几种基本数据类型是什么,各自占用多少字节 Java基本数据类型有8种: 名词解释: bit:位,计算机存储数据的最小单位,二进制数中的一个 位数. byte:字节,计算机存储数据的基本单位,一个字节由8位二进制数组成.通常一个汉字占两个字节. 2.String类能被继承吗,为什么. 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变. 关于final修饰符,介绍如下: 根据程序上下文环境,Java关键字final有“

SpringCloud微服务之跨服务调用后端接口

SpringCloud微服务系列博客: SpringCloud微服务之快速搭建EurekaServer:https://blog.csdn.net/egg1996911/article/details/78787540 SpringCloud微服务之注册服务至EurekaServer:https://blog.csdn.net/egg1996911/article/details/78859200 SpringCloud微服务之集成thymeleaf访问html页面/静态页面&热部署:https

.netcore 3.1高性能微服务架构:封装调用外部服务的接口方法--HttpClient客户端思路分析

众所周知,微服务架构是由一众微服务组成,项目中调用其他微服务接口更是常见的操作.为了便于调用外部接口,我们的常用思路一般都是封装一个外部接口的客户端,使用时候直接调用相应的方法.webservice或WCF的做法就是引用服务,自动生成客户端.在webapi2.0里,我们都会手动封装一个静态类.那么在.netcore3.1的微服务时代,我们该如何处理这个问题呢? ----思路都是一样的,封装一个外部服务,并且使用依赖注入和 HttpFactory工厂等.netcore特有的方式提升性能.接下来我们

基于 Docker 的微服务架构实践

本文来自作者 未闻 在 GitChat 分享的{基于 Docker 的微服务架构实践} 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 DevOps,也见证了 Docker 的技术体系的快速发展.本文主要是结合在公司搭建的微服务架构的实践过程,做一个简单的总结.希望给在创业初期探索如何布局服务架构体系的 DevOps,或者想初步了解企业级架构的同学们一些参考. Microservice 和 Docker 对于创业公司的技术布局,很多声