前言

ASP.NET Core Web API 接口限流、限制接口并发数量,我也不知道自己写的有没有问题,抛砖引玉、欢迎来喷!

需求

  1. 写了一个接口,参数可以传多个人员,也可以传单个人员,时间范围限制最长一个月。简单来说,当传单个人员时,接口耗时很短,当传多个人员时,一般人员会较多,接口耗时较长,一般耗时几秒。
  2. 当传多个人员时,并发量高时,接口的耗时就很长了,比如100个用户并发请求,耗时可长达几十秒,甚至1分钟。
  3. 所以需求是,当传单个人员时,不限制。当传多个人员时,限制并发数量。如果并发用户数少于限制数,那么所有用户都能成功。如果并发用户数,超出限制数,那么超出的用户请求失败,并提示"当前进行XXX查询的用户太多,请稍后再试"。
  4. 这样也可以减轻被请求的ES集群的压力。

说明

  1. 使用的是.NET6
  2. 我知道有人写好了RateLimit中间件,但我暂时还没有学会怎么使用,能否满足我的需求,所以先自己实现一下。

效果截图

下面是使用jMeter并发测试时,打的接口日志:

代码

RateLimitInterface

接口参数的实体类要继承该接口

using JsonA = Newtonsoft.Json;
using JsonB = System.Text.Json.Serialization; namespace Utils
{
/// <summary>
/// 限速接口
/// </summary>
public interface RateLimitInterface
{
/// <summary>
/// 是否限速
/// </summary>
[JsonA.JsonIgnore]
[JsonB.JsonIgnore]
bool IsLimit { get; }
}
}

接口参数实体类

继承RateLimitInterface接口,并实现IsLimit属性

public class XxxPostData : RateLimitInterface
{
...省略 /// <summary>
/// 是否限速
/// </summary>
[JsonA.JsonIgnore]
[JsonB.JsonIgnore]
public bool IsLimit
{
get
{
if (peoples.Count > 2) //限速条件,自己定义
{
return true;
}
return false;
}
}
}

RateLimitAttribute

作用:标签打在接口方法上,并设置并发数量

namespace Utils
{
/// <summary>
/// 接口限速
/// </summary>
public class RateLimitAttribute : Attribute
{
private Semaphore _sem; public Semaphore Sem
{
get
{
return _sem;
}
} public RateLimitAttribute(int limitCount = 1)
{
_sem = new Semaphore(limitCount, limitCount);
}
}
}

使用RateLimitAttribute

标签打在接口方法上,并设置并发数量。

服务器好像是24核的,并发限制为8应该没问题。

[HttpPost]
[Route("[action]")]
[RateLimit(8)]
public async Task<List<XxxInfo>> Query([FromBody] XxxPostData data)
{
...省略
}

限制接口并发量的拦截器RateLimitFilter

/// <summary>
/// 接口限速
/// </summary>
public class RateLimitFilter : ActionFilterAttribute
{
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
Type controllerType = context.Controller.GetType();
object arg = context.ActionArguments.Values.ToList()[0];
var rateLimit = context.ActionDescriptor.EndpointMetadata.OfType<RateLimitAttribute>().FirstOrDefault(); bool isLimit = false; //是否限速
if (rateLimit != null && arg is RateLimitInterface) //接口方法打了RateLimitAttribute标签并且参数实体类实现了RateLimitInterface接口时才限速,否则不限速
{
RateLimitInterface model = arg as RateLimitInterface;
if (model.IsLimit) //满足限速条件
{
isLimit = true;
Semaphore sem = rateLimit.Sem; if (sem.WaitOne(0))
{
try
{
await next.Invoke();
}
catch
{
throw;
}
finally
{
sem.Release();
}
}
else
{
var routeList = context.RouteData.Values.Values.ToList();
routeList.Reverse();
var route = string.Join('/', routeList.ConvertAll(a => a.ToString()));
var msg = $"当前访问{route}接口的用户数太多,请稍后再试";
LogUtil.Info(msg);
context.Result = new ObjectResult(new ApiResult
{
code = (int)HttpStatusCode.BadRequest,
message = msg
});
}
}
} if (!isLimit)
{
await next.Invoke();
}
}
}

注册拦截器

//拦截器
builder.Services.AddMvc(options =>
{
...省略 options.Filters.Add<RateLimitFilter>();
});

使用jMeter进行压力测试

测试结果:

  1. 被限速的接口,满足限速条件的调用并发量大时,部分用户成功,部分用户提示当前查询的人多请稍后再试。但不影响未满足限速条件的传参调用,也不影响其它未限速接口的调用。
  2. 测试的所有接口、所有查询参数条件的调用,耗时稳定,大量并发时,不会出现接口耗时几十秒甚至1分钟的情况。

ASP.NET Core Web API 接口限流的更多相关文章

  1. List多个字段标识过滤 IIS发布.net core mvc web站点 ASP.NET Core 实战:构建带有版本控制的 API 接口 ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目 Using AutoFac

    List多个字段标识过滤 class Program{  public static void Main(string[] args) { List<T> list = new List& ...

  2. ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件

    前言: 从开始学习Vue到使用element-ui-admin已经有将近快两年的时间了,在之前的开发中使用element-ui上传组件el-upload都是直接使用文件选取后立即选择上传,今天刚好做了 ...

  3. 在ASP.NET Core Web API上使用Swagger提供API文档

    我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...

  4. 在Mac下创建ASP.NET Core Web API

    在Mac下创建ASP.NET Core Web API 这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢? 原因如下: 官方文档涉 ...

  5. 在ASP.NET Core Web API中为RESTful服务增加对HAL的支持

    HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务 ...

  6. ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现

    很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构.这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地 ...

  7. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行代码就展示了一个基本工作原理.然而,要将这样的解决方案运用到实际生产环境,还有很 ...

  8. ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...

  9. ASP.NET Core Web APi获取原始请求内容

    前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...

  10. ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目

    一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自 ...

随机推荐

  1. Software--电商平台系统--P3 Product Catalogy 商品目录模块

    2018-01-15  15:25:20 商品目录 服务层 控制器层 ProductCate 服务层 Controller 控制器层

  2. Linux awk 替换文本字符串内容

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  3. mobx基础

    React 和 MobX 是一对强力组合.React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染.而MobX提供机制来存储和更新应用状态供 React 使用. 对于应用开发中的常见问题,R ...

  4. UNIT ONE

    一.机器语言 1.机器指令         0与1构成 2.机器可以直接执行 二.汇编语言 1.汇编指令       要翻译成机器指令,机器才可以运行 2.给人看的,主要是人看得懂 VS 机器.汇编. ...

  5. arm开发环境搭建

    1.smaba   在Linux PC安装smaba    sudo apt-get install samba编辑/etc/samba/smb.conf配置:[yz]path = /home/yzv ...

  6. Docker基本命令之 容器运行命令参数

    容器命令行参数介绍: docker run:顾名思义就是运行一个Docker 以下是具体参数介绍: -a: stdin:指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项 - ...

  7. centos安装docker显示 No package docker-ce available

    温馨提醒,docker内核版本必须是3.10+以上的版本 查看方式 uname -r 1. 卸载老版本的 docker 及其相关依赖 sudo yum remove docker docker-com ...

  8. Python 错误:ModuleNotFoundError: No module named 'conf'

    问题描述: 编译器无法使用cmd命令来执行py文件,结果可能报ModuleNotFoundError的错误. 比如在cmd任务栏执行:python E:\myProgram\Python\spider ...

  9. Ubuntu系统update时提示源不安全被禁用的一种解决办法

    参考自这篇文章Ubuntu系统update时提示源不安全被禁用 - 知乎 (zhihu.com). 安装好Ubuntu18.04并更换清华源后,在运行 sudo apt update 更新源时报错如下 ...

  10. BGP反射器

    路由反射器是一种减少自治系统内IBGP对等体连接数量的方法. 根据BGP路由通告原则,要求一个AS内的所有BGP Speaker将建立全连接关系(BGP Speaker两两建立邻接关系).当AS内的B ...