首页 > 其他分享 >接口并发解决方案

接口并发解决方案

时间:2023-06-03 10:32:11浏览次数:27  
标签:缓存 请求 解决方案 接口 并发 算法 限流

设定一个场景,假如一个商品接口在某段时间突然上升,会怎么办?

生活中的例子来说,假设冰墩墩在当天晚上上热搜之后,迅速有十几万人去淘宝下单购买,此时并没有做好对该商品的缓存预热以及准备,如何操作?

对于这个问题,在电商高并发系统中,对接口的保护一般采用:缓存、限流、降级 来操作。

假设该接口已经接受过风控的处理,过滤掉一半的机器人脚本请求,剩下都是人为的下单请求。

服务限流

限流 主要的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理。

限流算法

1. 漏斗算法

漏桶算法 是当请求到达时直接放入漏桶,如果当前容量已达到上限(限流值),则进行丢弃或其他策略(触发限流策略)。漏桶以固定的速率(根据服务吞吐量)进行释放访问请求(即请求通过),直到漏桶为空。

漏斗算法的思想就是,不管你来多少请求,我的接口消费速度一定是小于等于流出速率的阈值的。

接口并发解决方案_Linux运维

可以基于消息队列来实现。

2. 令牌桶算法

令牌桶算法 是程序以v(v = 时间周期 / 限流值)的速度向令牌桶中增加令牌,直到令牌桶满,请求到达时向令牌桶请求令牌,如果获取成功则通过请求,如果获取失败触发限流策略。

令牌桶算法和漏斗算法的思想差别在于,前者可以允许突发请求的发生。


接口并发解决方案_限流_02

3. 滑窗算法

滑窗算法 是将一个时间周期分为N个小周期,分别记录每个小周期内访问次数,并且根据时间滑动删除过期的小周期。

如下图所示,假设时间周期为1分钟,将1分钟再分为2个小周期,统计每个小周期的访问数量,则可以看到,第一个时间周期内,访问数量为75,第二个时间周期内,访问数量为100,如果一个时间周期内所有的小周期总和超过100的话,则会触发限流策略。

接口并发解决方案_消息队列_03

Sentinel的实现 和 TCP滑窗。

接入层限流

Nginx限流

Nginx 限流采用的是漏桶算法。

它可以根据客户端特征,限制其访问频率,客户端特征主要指 IP、UserAgent等。使用 IP 比 UserAgent 更可靠,因为 IP 无法造假,UserAgent 可随意伪造。

limit_req模块基于IP:Module ngx_http_limit_req_module 

tgngine:ngx_http_limit_req_module - The Tengine Web Server

本地接口限流

Semaphore

Java 并发库 的 Semaphore 可以很轻松完成信号量控制,Semaphore 可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

假如我们对外提供一个服务接口,允许最大并发数为40,我们可以这样:

private final Semaphore permit = new Semaphore(40, true);

public void process(){

    try{
        permit.acquire();
        //TODO 处理业务逻辑

    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        permit.release();
    }
}

具体的 Semaphore 实现参考源码。

分布式接口限流

使用消息队列

不管是用MQ中间件,或是Redis的List实现的消息队列,都可以作为一个 缓冲队列 来使用。思想就是基于漏斗算法。

当对于一个接口请求达到一定阈值时,就可以启用消息队列来进行接口数据的缓冲,并根据服务的吞吐量来消费数据。

接口并发解决方案_限流_04

服务降级

在接口做好风控的前提下,发现了接口请求的并发量迅速上升,我们可以启用兜底方案,进行服务降级。

一般服务降级应该用来对一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。

降级方案

停止边缘业务

比如淘宝双11前,就不可以查询三个月前的订单,对边缘业务进行降级,保证核心业务的高可用。

拒绝请求

在接口请求并发量大于阈值,或是接口出现大量失败请求等等突发情况,可以拒绝一些访问请求。

拒绝策略

  • 随机拒绝:随机拒绝超过阈值的请求 。
  • 拒绝旧请求:按照请求的时间,优先拒绝更早收到的请求。
  • 拒绝非核心请求:根据系统业务设置核心请求清单,将非核心清单内的请求拒绝掉。

恢复方案

在实现服务降级之后,对于突增流量我们可以继续注册多个消费者服务来应对并发量,之后我们再对一些服务器进行慢加载。

降级具体实现参考其他文章。

数据缓存

在接口做好风控的前提下,发现了接口请求的并发量迅速上升,我们可以分以下几个操作执行:

  1. 对访问请求使用分布式锁进行阻塞。
  2. 在这个短时间中,我们可以将对应操作行的热点数据,缓存在缓存中间件中。
  3. 放行请求后,让所有请求优先操作缓存数据。
  4. 再将操作的结果通过消息队列发送给消费接口慢慢消费。

接口并发解决方案_消息队列_05

缓存问题

假设我们操作的是一个库存接口,此时数据库中只有100个库存。

那假如此时我们将一条数据放入缓存中,如果所有的请求都来访问这个缓存,那它还是被打挂,我们该怎么操作?

读写分离

第一种想法,读写分离。

使用Redis的哨兵集群模式来进行主从复制的读写分离操作。读的操作肯定大于写操作,等库存被消费到0时,读操作直接快速失败。

接口并发解决方案_限流_06

负载均衡

第二种想法,负载均衡。

在缓存数据后,如果所有请求都来缓存中操作这个库存,不管是加悲观锁还是乐观锁,并发率都很低,此时我们可以对这个库存进行拆分。

我们可以参照 ConcurrentHashMap 中的 counterCells 变量的设计思想,将100个库存拆分到10个缓存服务中,每个缓存服务有10个缓存,然后我们再对请求进行负载均衡到各个缓存服务上。

但是这种方式会有问题,如果大部分用户被hash到同一个缓存上,导致其他缓存没有被消费,却返回没有库存,这是不合理的。

接口并发解决方案_消息队列_07

page cache

第三种想法,page cache。

大部分软件架构其实都用到了这种方法,比如linux内核的硬盘写入、mysql的刷盘等等,即将短时间内的写操作聚合结果写入,所有的写操作在缓存内完成。

标签:缓存,请求,解决方案,接口,并发,算法,限流
From: https://blog.51cto.com/jowin/6407555

相关文章

  • 接口基础
    服务器地址-接口地址api.keyou.site:8000/configures接口分类1、硬件接口:指的是两个硬件设备之间的连接方式(比如:鼠标和电脑通过usb接口进行连接)2、软件接口:简单来说就说软件程序之间数据交互的通道软件接口分类:1、程序内部接口:是客户端与服务器的接口,用来实现客户端和服务......
  • 存储接口测试简介与测试方法
    本文分享自天翼云开发者社区《存储接口测试简介与测试方法》,作者:杨****鹏 1、接口测试的概念接口测试原理是通过测试程序模拟客户端向服务器发送请求报文,服务端接收报文并处理后再把应答报文发送回客户端,客户端接收应答报文的过程测试接口目的就是保证接口调用的正确性和稳......
  • centos7卡在sda assuming drive cache write through不能进入操作系统的一个解决方案
    1、https://blog.csdn.net/shishui07/article/details/113934961?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-5-113934961-blog-101298947.235^v36^pc_relevant_default_base3&spm=1001.2101.3001.4242.4&utm_rel......
  • postman接口关联
    在使用postman做接口测试时,有时候后面的接口需要获取前面接口的某一个返回值做为请求参数,这时就可以使用关联。如从A接口提取出a字段的值,供B接口的b字段使用。一个接口的返回报文如下:{"retCode":"0","retMsg":"请求成功","rspData":{"status":"1",......
  • 补充知识:集合的并发修改异常
             ......
  • 资讯接口
    习题链接消失的Token课程列表使用node来编写一个简单API接口当我访问/news要返回一个数据对象给我当我访问其他的路径均返回404关键点node基础知识点http模块使用require导入http模块使用http模块中的createServer方法来创建HTTP服务器在req中的url属性进行设......
  • 项目访问的端口是8018,但是真实接口地址是19080,导致访问这个地址http://9.6.237.104:80
    这个问题是由于您的前端页面与后端应用程序的接口地址不在同一个域名下所引起的跨域请求。在浏览器中,出于安全考虑,通常不允许JavaScript从一个域名下访问另一个不同域名下的资源,这种行为被称为跨域请求(Cross-OriginResourceSharing,CORS)。有一些方法可以解决跨域问题,下面是......
  • 爱博精电物业管理一站式综合能源管控解决方案惊艳亮相第五届SPME上海国际物业管理产业
    5月31日,2023第五届SPME上海国际物业管理产业博览会正式启幕。本届活动以“凝心聚力 蓄势破局”为主题,展览面积超22000m²,汇聚500多家参展商,设置八大展区。多方面向业主与物业方展示物业管理行业最新的产品、技术及智慧管理解决方案。本次会议旨在通过各界翘楚、智囊协同发力,开启数......
  • Day07-抽象类和接口
    抽象类不能new这个抽象类,只能靠子类去实现它,约束!抽象类可以写普通方法抽象方法必须写在抽象类中接口接口中的所有定义其实都是抽象的publicabstract类可以实现接口implements接口实现了接口的类,就需要重写接口中的方法利用接口实现多继承接口不能被......
  • Beginner:Client libraries-7实现自定义接口
    目标:在ROS2中学习更多的实现自定义接口背景在指定的接口包中声明接口,有时在一个包中声明、创建、使用所有接口很方便。本教程关注msg接口类型,但是步骤对于其他所有接口类型适用。任务1、创建一个包ros2pkgcreate--build-typeament_cmakemore_interfacesmkdirmore_in......