【发布时间】:2019-01-07 18:39:43
【问题描述】:
我有一个在 Kestrel(Ubuntu) 下运行的 ASP.NET Core Web API,我遇到了一个奇怪的情况: 当我运行前 20 次 API 调用系列时,前 3-5 次调用很慢,然后响应时间还可以。 然后我做了一个短暂的延迟(可能是一分钟甚至更短)并再次运行一系列 API 调用,前几次调用再次非常慢,只有在前 3-5 次调用之后响应时间才正常。
最初,我认为问题出在 Kestrel 配置中,因此我进行了以下设置:
var host = new WebHostBuilder()
.UseKestrel(options =>
{
options.Limits.MaxConcurrentConnections = 200;
options.Limits.MaxConcurrentUpgradedConnections = 200;
options.Limits.MaxRequestBodySize = 10000;
options.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)));
options.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)));
options.Limits.KeepAliveTimeout = TimeSpan.FromDays(2);
})
.UseConfiguration(config)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
它帮助我使我的服务更快地工作,但问题仍然存在。
服务的基本逻辑如下: 1) 获取请求对象 2)解析成POCO类的实例 3) 使用多个 SELECT 调用数据库以获取所有必需的数据(为此,我使用 Dapper 和允许一次性运行多个 SQL 查询的方法) 4) 用新接收到的数据更新对象的实例并将对象插入到DB中
就是这样。
我不知道是什么导致了这种延迟(空闲时间)。
我猜测也许我应该进行一些虚拟调用来保持服务运行。因此,我添加了一个包含 Timer 作业的 Singleton,以每隔一分钟查询数据库以获取一些查找数据。但它没有帮助。
然后我尝试添加另一个计时器作业来查询步骤 N3 中仅针对 DB 中的第一条记录所需的数据,没有一些特定的 req 参数并且它没有帮助,而且它开始工作更慢。
我还在表上添加了索引,以使 SELECT 更快地工作,另外我在所有 SELECT 中添加了 WITH(NOLOCK) 语句,但它没有帮助。
有什么想法吗,伙计们?
【问题讨论】:
-
可能与 SQL Max Pool Size (in connection string) 相关?
-
SQL Server 将它读取的数据页缓存到内存中(您可以使用
SET STATISTICS IO ON查看),这可能涉及到。 -
如果您能提供minimal reproducible example,那就太好了。
-
我也有同样的问题。我不知道原因,但是经过一些空闲时间后请求很慢,下一个请求很快。并且该服务始终处于开启状态并且没有数据库连接。看起来 Kestrel 在内部是如何实现的。
标签: c# sql-server asp.net-mvc asp.net-core kestrel