YARP 默认配置能否扛住高并发?
不能直接扛。YARP 本身基于 ASP.NET Core 的
HttpClient和
HttpProxy构建,底层复用
HttpClientHandler连接池和
ThreadPool,但默认的
MaxConnectionsPerServer(默认 2)和
ThreadPool队列行为会成为瓶颈——尤其在短连接、高 QPS 场景下,你很快会看到
HttpRequestException: Connection refused或大量
TimeoutException。
必须调优的三个核心 HttpClientHandler 参数
YARP 的转发通道由
ClusterConfig中的
Destinations关联到
HttpClient实例,而该实例的
Handler才决定连接能力。你需要显式配置
HttpClientHandler并注入:
MaxConnectionsPerServer:建议设为
100~
500(视后端节点数和单机资源而定),避免连接耗尽
MaxRequestContentBufferSize:默认
2GB,但大上传会拖慢线程池;如无大文件转发,可设为
10 * 1024 * 1024(10MB)
AutomaticDecompression:设为
GZip | Deflate可减少带宽,但增加 CPU;若后端已压缩且代理不改响应体,建议关闭以降低开销
var handler = new HttpClientHandler
{
MaxConnectionsPerServer = 200,
MaxRequestContentBufferSize = 10 * 1024 * 1024,
AutomaticDecompression = DecompressionMethods.None
};避免 ThreadPool 饥饿:禁用同步 IO + 控制并发请求数
YARP 在转发时若遇到阻塞式中间件(如未用
await的
HttpContext.Request.Body.ReadAsync)、或下游响应极慢,会导致
ThreadPool工作线程被长期占用。解决方案不是加线程数,而是切断阻塞源头: 确保所有自定义中间件使用异步 API(
ReadAsync/
WriteAsync),禁用
AllowSynchronousIO = true在
Program.cs中显式限制并发请求数:用
WebHostBuilder.ConfigureKestrel设置
LimitMaxConcurrentConnections和
LimitMaxConcurrentUpgradedConnections对异常慢的下游服务启用
TimeoutPolicy:通过
RouteConfig的
Timeout属性(单位秒)快速失败,避免线程卡死
真实压测中容易被忽略的点
本地
ab或
wrk压测时,Windows 默认的
MaxUserPort(约 65535)和
TCPTimedWaitDelay(240 秒)会让客户端快速耗尽可用端口,表现为大量
Connection reset by peer——这不是 YARP 的问题,而是发起方的限制。解决方式包括: 压测机上修改注册表:
MaxUserPort = 65534,
TCPTimedWaitDelay = 30用
HttpClient池替代每次新建实例(YARP 内部已做,但自定义路由策略里别手写 new HttpClient) 检查后端服务是否启用了 HTTP/2(YARP 支持,但需 .NET 6+ + TLS + ALPN),HTTP/2 多路复用能显著降低连接数压力
