【发布时间】:2017-04-03 21:39:12
【问题描述】:
代码在我的开发环境中运行良好,但在使用可扩展架构部署时,它似乎死锁了。
这里的目标是获取 API 请求队列以发送到 SendGrid,将它们分批并一次处理每个批次。
来自 ASHX 处理程序的第一次调用
public void ProcessRequest(HttpContext context)
{
var result = Code.Helpers.Email.Sendgrid.Queue.Process().Result;
if (result.Success)
{
Queue.Process()
public static async Task<GenericMethodResult> Process()
{
var queueItems = GetQueueItemsToProcess();
var batches = BatchQueueItems(queueItems);
foreach (var batch in batches)
{
var r = await batch.SendToSendGrid();
if (r.StopBatch)
{
break;
}
}
return new GenericMethodResult(true);
}
SendToSendGrid()
public async Task<SendGridAPIMethodResponse> SendToSendGrid()
{
var r = new SendGridAPIMethodResponse();
var json = API.Functions.CreateJSONData(this);
var sg = new SendGridClient(Settings.Email.SendgridAPIKey);
dynamic response;
if (Action == Action.UpdateRecipient)
{
response = await sg.RequestAsync(SendGridClient.Method.PATCH, urlPath: "contactdb/recipients", requestBody: json);
}
string jsonResponse = response.Body.ReadAsStringAsync().Result;
// Process response...
return r;
}
我已经尽可能多地删除了代码。
有人能告诉我为什么这段代码在生产中会超时吗?
【问题讨论】:
-
您似乎是直接从处理程序发送电子邮件。虽然这可行,但最好通过background job 发送电子邮件。如果电子邮件服务器(或本例中的 Web 服务器)很慢怎么办?或者如果它暂时关闭怎么办?可能更好地将电子邮件排队并能够重试发送等。
-
@Mason 它没有发送电子邮件,而是将联系人数据与他们的联系人 API 同步。它具有合理的速率限制,因此每分钟最多只能执行约 50 次。它被一个分布式锁锁定,所以如果再次调用它,它会在忙碌时简单地返回而不做任何事情。如果失败,它不会从队列中删除项目,稍后会重试。它被设置为 Azure 计划任务,每分钟调用一次此 URL。由于缓存,很难将其与网站本身分离。
-
这仍然是一个外部服务调用。由你决定。我只是讨厌我的应用程序的用户仅仅因为其他一些 3rd 方服务缓慢/不可用而获得缓慢/糟糕的体验。
-
@Mason 如何降低用户体验?这是一个相当简单的队列处理器。队列引入的延迟对最终用户是不可见的。
-
啊,我现在看到您已经更新了您的评论,即由于用户交互,它是由计划任务而不是通过 AJAX 调用的。好的,所以你是对的,在这种情况下它不会减慢用户的速度。但随之而来的问题是,为什么要通过 ASP.NET 站点中的处理程序公开功能?为什么不让计划任务直接运行代码或使用更适合 Azure 中的工作的东西?
标签: c# asp.net async-await deadlock