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技能
点赞和在看就是最大的支持❤️
返回搜狐,查看更多
责任编辑:
平台声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
阅读 (
)