ASP.NET Core 中间件与请求管道:手写一个限流中间件
Words: 950Read Time: 3 minLast edited: 2026-8-4
请求管道是怎么跑的
ASP.NET Core 的请求处理模型和老 ASP.NET 的 HttpModule/HttpHandler 完全不同,它就是一条中间件串起来的管道。请求进来后从第一个中间件开始挨个往下走,响应时再按相反的顺序走回来。
官方文档里那张「洋葱图」很形象:每个中间件既能在请求到达下一个中间件之前做点事,也能在响应返回时再做点事。一个最简管道长这样:
Use 和 Run 的区别
Use:执行完自己的逻辑后,可以选择调用next()把请求传给下一个中间件
Run:管道终点,执行完就结束了,后面注册的东西不会再跑到
这里有个容易忽视的点:调用
next() 是可选的。不调,请求到这里就「短路」了。权限校验、限流这类中间件恰恰靠短路吃饭——发现不对劲,直接写个 401 或 429 响应返回,后面的 MVC 根本不执行。我刚上手时犯过一个低级错误:在
Use 里写了逻辑却忘了 await next(),结果所有请求都返回空白,查了半天才发现。手写一个限流中间件
最近给自己的小站加接口保护,需求很简单:同一个 IP 一分钟内最多请求 60 次,超了就返回 429。用内存计数器实现一个固定窗口限流:
注册用
app.UseMiddleware<RateLimitMiddleware>() 就行。这个方案上了生产肯定不够(单机内存状态、窗口边界会有突刺流量),但作为学习和内部小项目够用,真要上量可以换滑动窗口或者基于 Redis 的分布式方案。注册顺序的坑
「中间件的注册顺序就是执行顺序」,这句话背下来能避开八成的坑。我自己踩过两个:
- 限流注册得太靠后。我把限流写在
UseAuthorization后面,结果每个请求都先走了一遍鉴权才被限流,白白浪费资源。限流应该尽量靠前,把垃圾流量挡在门外。
- 静态文件把请求短路了。
UseStaticFiles对命中的静态文件直接返回,不往后走。我一开始指望自定义的日志中间件能记录静态资源访问,发现一条日志都没有,才明白它前面就被短路了。
一般推荐的骨架是:异常处理 → HTTPS 重定向 → 静态文件 → 路由 → 认证 → 授权 → 自定义业务中间件 → 终结点。自定义中间件往哪插,取决于它需要在哪一层生效:挡恶意流量就尽量靠前,要做业务相关的加工就放到认证授权之后。
中间件本身不难写,难的是想清楚它在管道里的位置。
Loading...