我们最近开发了基于SOA的网站,但这个网站最后不得不可怕的负载和性能问题时,它负载下去。我张贴有关这个问题在这里一个问题:异步并等待:它们不好吗?
ASP.NET website becomes unresponsive under load
该网站由被4个节点的集群,这是另一个4-托管的网站上托管的API(WEB API)网站节点集群并调用API。两者都是使用ASP.NET MVC 5开发的,所有操作/方法都基于异步等待方法。
在一些监控工具(如NewRelic)下运行该站点后,调查几个转储文件并分析工作进程,结果发现在非常轻的负载下(例如16个并发用户),我们最终有大约900个线程利用100%的CPU并填满IIS线程队列!
即使我们设法通过引入大量缓存和性能修正功能将站点部署到生产环境中我们团队中的许多开发人员都认为我们必须删除所有异步方法并将API和网站转换为普通的Web API以及只返回Action结果的Action方法。
我个人不是很满意的方法,因为我的直觉是,我们还没有使用的异步方法正确,否则就意味着,微软已经推出了一个功能,基本上是相当的破坏性,无法使用!
你知道,将其清除出是在哪里以及如何异步方法应该/可以使用任何参考?我们应该如何使用它们来避免这样的戏剧?例如根据我在MSDN上阅读的内容,我认为API层应该是异步的,但网站可能是一个正常的非异步ASP.NET MVC网站。
更新:
这里是异步方法,使所有与API通信。
public static async Task<T> GetApiResponse<T>(object parameters, string action, CancellationToken ctk)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(BaseApiAddress);
var formatter = new JsonMediaTypeFormatter();
return
await
httpClient.PostAsJsonAsync(action, parameters, ctk)
.ContinueWith(x => x.Result.Content.ReadAsAsync<T>(new[] { formatter }).Result, ctk);
}
}
这种方法有什么愚蠢的东西吗?请注意,当我们将所有方法转换为非异步方法时,我们获得了更好的性能。
下面是一个示例用法(我剪掉了与验证,日志记录等有关的代码的其他部分。此代码是MVC操作方法的主体)。
在我们服务的包装:
public async static Task<IList<DownloadType>> GetSupportedContentTypes()
{
string userAgent = Request.UserAgent;
var parameters = new { Util.AppKey, Util.StoreId, QueryParameters = new { UserAgent = userAgent } };
var taskResponse = await Util.GetApiResponse<ApiResponse<SearchResponse<ProductItem>>>(
parameters,
"api/Content/ContentTypeSummary",
default(CancellationToken));
return task.Data.Groups.Select(x => x.DownloadType()).ToList();
}
而且在行动:
public async Task<ActionResult> DownloadTypes()
{
IList<DownloadType> supportedTypes = await ContentService.GetSupportedContentTypes();
有关应用程序如何使用async/await的任何示例?当与IO绑定操作(如数据库调用和文件操作)一起使用时,通常应该提高可伸缩性,而不是降低它。如果它产生了不必要的线程,那么每个方法都可以标记为异步,这可能是一个红旗,可能是你的问题的原因。 –
也许,你的代码使用'Task.Run'封装同步API,而不是使用自然的异步API? http://stackoverflow.com/q/21690385/1768303。通常,在服务器上使用'Task.Run'是个不错的主意。 – Noseratio
是MVC 5吗?或者你的标签说MVC 3? –