添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

1、写了一个接口,参数可以传多个人员,也可以传单个人员,时间范围限制最长一个月。简单来说,当传单个人员时,接口耗时很短,当传多个人员时,一般人员会较多,接口耗时较长,一般耗时几秒。

2、当传多个人员时,并发量高时,接口的耗时就很长了,比如100个用户并发请求,耗时可长达几十秒,甚至1分钟。

3、所以需求是,当传单个人员时,不限制。当传多个人员时,限制并发数量。如果并发用户数少于限制数,那么所有用户都能成功。如果并发用户数,超出限制数,那么超出的用户请求失败,并提示"当前进行XXX查询的用户太多,请稍后再试"。

4、这样也可以减轻被请求的ES集群的压力。

1、使用的是.NET 6

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

if (peoples.Count > 2 ) //限速条件,自己定义

return true ;

return false ;

RateLimitAttribute

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

namespace Utils

/// <summary>

/// 接口限速

/// </summary>

public class RateLimitAttribute : Attribute

private Semaphore _sem;

public Semaphore Sem

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.ActionDeor.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 ))

await next.Invoke;

catch

throw ;

finally

sem.Release;

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分钟的情况。

- EOF -

点击标题可跳转

三步实现 ASP.NET Core 集成 ChatGPT

.NET 使用 Coverlet 统计单元测试覆盖率

C# 异步多线程的本质,上下文流转和同步

看完本文有收获?请转发分享给更多人

推荐关注「DotNet」,提升.Net技能

点赞和在看就是最大的支持❤️ 返回搜狐,查看更多

责任编辑:

平台声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
阅读 ( )