【发布时间】:2021-03-25 05:24:55
【问题描述】:
问题是 CPU 经常从 ~10% 飙升到 70% 以上:
不幸的是,这似乎对平均响应时间产生了影响,导致那里也出现了一些峰值。
这是一个令人愉快的场景,平均保持在 1 秒以下,但有时它的表现可能很差。
我曾尝试从 Azure 门户调查此问题,但我注意到一些请求保留在此块中,让我认为这是一个查询问题(从我所见,这并不完全是堆栈跟踪, GetValidFunction() 内可能有多个查询通过此处未显示的另一服务进行)。
如果是这种情况,我在内部重写查询没有问题,因为它们是通过 LINQ 和 EF 完成的,但后来我注意到了一些奇怪的事情。请注意,在此请求中,正在等待 Framework/Library CEEJitInfo::allocMem
对于另一个请求,正在为 REDIS 查询发生等待块。但大多数情况下,呼叫似乎被阻止在GetResults() 内,就像第三张图片一样。所有这些等待时间是否仅与数据库查询有关? (DTU 也有尖峰,但这是我必须解决的另一个问题 - 可能是由于设计不佳,很多表的 GUID 为 PK / FK - 索引重建可能?但这将在下次解决)
为这个应用程序提供一些上下文:
- 在 .NET 5 上运行的 Web API
- 允许用户创建自己的剃须刀模板
- 模板存储在 SQL Server 数据库中
- 查询模板,然后在运行时编译和渲染
我想到的另一个可能的原因是大量编译的剃须刀模板。这些视图可能有数百个,甚至上千个。我正在考虑框架内部正在执行的视图缓存失效问题,从而强制重新编译视图?
这可能与最初的问题有点偏离主题,但有人知道 razor 运行时编译在 ASP.NET Core 中是如何工作的吗?
具体来说:
- 这些视图在缓存中保留了多长时间?
- 是像在 .NET Framework 中那样为每个视图创建一个 DLL,还是只保存在内存中?
我试图寻找这两个问题的答案,但找不到任何答案。
总而言之,如果您对 CPU 峰值/等待时间问题有一些建议,我将不胜感激。您是否知道任何可能导致查询本身等待时间的原因?会不会和视图重编译/垃圾收集器有关?
感谢您的宝贵时间。
后期编辑: 执行的代码类似这样
Controller-> GET ExecuteFunction(functionCode) -> ValidateFunction(functionCode) -> GetValidFunction(functionCode)
ValidateFunction 也在执行其他查询,但在GetValidFunction 之后。
private (string, Functions) GetValidFunction(Guid functionCode)
{
var cacheKey = CacheKeys.FunctionError(functionCode);
var cacheTimeSpan = new TimeSpan(0, cacheValidationMinutes, 0);
var validationErrorMessage = cacheProvider.GetWithSlidingExpiration<string>(cacheKey, cacheTimeSpan);
var function = functionLogic.GetValidFunctionByCode(functionCode);
if (function == null)
{
cacheProvider.AddToCacheInvariantCase(cacheKey, invalidErrorCode, cacheTimeSpan);
return (invalidErrorCode, null);
}
if (string.isNullOrEmpty(validationErrorMessage)) return (validationErrorMessage, function);
var functionCodeData = functionCodeLogic.GetFunctionCode(functionCode);
if (functionCodeData == null)
{
cacheProvider.AddToCacheInvariantCase(cacheKey, invalidErrorCode, cacheTimeSpan);
return (invalidErrorCode, null);
}
if (function.StatusId == (int)FunctionStatusName.Active || function.StatusId == (int)FunctionStatusName.Draft)
{
cacheProvider.AddToCacheInvariantCase(cacheKey, NoErrorFunction, cacheTimeSpan);
}
return (null, function);
}
GetValidFunction 内部的查询会执行这个逻辑
public T Get(Expression<Func<T, bool>> where)
{
return dbset.Where(where).FirstOrDefault();
}
【问题讨论】:
-
你看请求数了吗?你已经在使用
async await-pattern了吗? -
听起来涉及到很多活动部件。您能否简化或排除解决方案中的某些方面,看看是否遇到同样的问题?
-
在我看来,您正在某个地方进行同步(阻塞)I/O 调用,这会导致线程争用。除非您共享相关的代码,否则有人无法进行故障排除!特别是我有兴趣看到 I/O (DB) 调用以及调用者直到顶部。
-
@Remus - 我认为请求的是 IsValidFunction 中的代码以及如何从控制器调用它。没有代码很难调试问题。
-
你为什么使用 GetResults() ?,你能一直做异步调用而不是使用 GetResults 吗?
标签: c# .net azure asp.net-core azure-web-app-service