AWS Dynamo DB上的400错误请求作为ASP.NET的会话提供程序

时间:2014-05-07 21:39:09

标签: asp.net-mvc-4 session amazon-web-services session-state amazon-dynamodb

我们在应用中使用AWS's DynamoDB Session Provider来存储会话数据。

我最近搬到了一个可以让NewRelic监控我的应用程序的环境,它开始抛出有关Dynamo DB访问的警报。但是,NewRelic是获得它的唯一监控工具。我在应用程序日志记录(log4net)或Windows事件查看器中看不到与此问题相关的任何内容。

我搜索了很多,甚至浏览了提供商的源代码,但结果是空的。

我得到(400)错误请求似乎是在每小时发生3或4次的1或2分钟内所做的所有通话。

我能得到的堆栈跟踪并不乐观:

at System.Net.HttpWebRequest.GetResponse()
at System.Net.HttpWebRequest.GetResponse()
at Amazon.Runtime.AmazonWebServiceClient.getResponseCallback(IAsyncResult result)

违规网址为:

dynamodb.us-east-1.amazonaws.com/Stream/GetResponse

从下面的时间图中我们可以看到所有请求在大多数时间都很好(图1),但是当问题发生时,对DynamoDB的成功请求数变为0(图1)。而且,与此同时,抛出的错误数量也出现了飙升(图2)。


更新:在周末的低使用期间,我在生产服务器上运行Fiddler,看看AWS的错误是什么样的。我得到"条件请求失败"这似乎是因为在请求和旧值时更新了值,因此值与预期值不一致。以下是完整的请求/回复作为样本。

请求:


POST https://dynamodb.us-east-1.amazonaws.com/ HTTP/1.1
X-Amz-Target: DynamoDB_20120810.UpdateItem
Content-Type: application/x-amz-json-1.0
User-Agent: aws-sdk-dotnet-35/2.0.15.0 .NET Runtime/4.0 .NET Framework/4.0 OS/6.2.9200.0 SessionStateProvider TableSync
Host: dynamodb.us-east-1.amazonaws.com
X-Amz-Date: 20140510T153947Z
X-Amz-Content-SHA256: e7a4886acac6ccf16f0da9be962d3a68bd50e381c202277033d0d2bb3208aa8a
Authorization: AWS4-HMAC-SHA256 Credential=redacted/20140510/us-east-1/dynamodb/aws4_request, SignedHeaders=content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=redacted
Accept: application/json
X-NewRelic-ID: redacted
X-NewRelic-Transaction: redacted
Content-Length: 399

{
    "TableName": "ASP.NET_SessionState",
    "Key": {
        "SessionId": {
            "S": "redacted"
        }
    },
    "AttributeUpdates": {
        "LockId": {
            "Value": {
                "S": "42a9ed29-7a92-4455-8733-2f56c7d974b3"
            },
            "Action": "PUT"
        },
        "Locked": {
            "Value": {
                "N": "1"
            },
            "Action": "PUT"
        },
        "LockDate": {
            "Value": {
                "S": "2014-05-10T15:39:47.324Z"
            },
            "Action": "PUT"
        }
    },
    "Expected": {
        "Locked": {
            "Value": {
                "N": "0"
            },
            "Exists": true
        }
    },
    "ReturnValues": "ALL_NEW"
}

响应:


HTTP/1.1 400 Bad Request
x-amzn-RequestId: redacted
x-amz-crc32: redacted
Content-Type: application/x-amz-json-1.0
Content-Length: 120
Date: Sat, 10 May 2014 15:33:17 GMT

{
    "__type": "com.amazonaws.dynamodb.v20120810#ConditionalCheckFailedException",
    "message": "The conditional request failed"
}

图1

Non Web Transactions - Graph 1

图2

Errors - Graph 2

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:3)

如果您的应用程序在访问会话状态的同时发出多个请求,则可能发生条件锁定失败。这在Ajax调用中很常见。文章The Downsides of ASP.NET Session State提供了一个很好的解释,说明ASP.NET如何通过一些解决方法序列化对特定会话状态的访问:

  

我们要看的第一个问题是许多开发人员不了解的问题;默认情况下,ASP.NET管道不会同时处理属于同一会话的请求。它将它们串行化,即它按照它们被接收的顺序对它们进行排队,以便它们被串行处理而不是并行处理。 [...]

这些错误不应该冒泡到应用程序级别。 AWS SDK for .NET抛出条件更新失败的异常,会话提供程序将其解释为无法获取锁定。这被传递回ASP.NET框架,该框架将请求排队直到它可以获得锁定:

  

[...]这意味着如果请求正在进行且来自同一会话的另一个请求到达,则它将排队等待仅在第一个请求完成时开始执行。为什么ASP.NET会这样做?对于并发控制,以便多个请求(即多个线程)不以不一致的方式读取和写入会话状态。

答案 1 :(得分:1)

更新

Norm Johanson's answer表明了手头问题的根本原因,我保留了针对仍然适用的部分和相关问题指针的相应调整答案。


初步答复

我还没有遇到您描述的确切问题,但它在调查AWS API Eventual Consistency的背景下遇到类似模式时敲响了警钟,例如,我对Deterministically creating and tagging EC2 instances的回答更多。从那时起,情况有了很大改善:

现在,我怀疑是这样的:

  • New Relic正在检测.NET字节代码,它允许它们例如记录所有异常,无论是否处理它们。
  • 您的客户是例如因请求限制违规而受到限制,导致API Error Codes导致可重试的400 - ThrottlingException,即它会触发一个异常处理并依次启动指数重试,最终最终成功完成请求,并且因此不会留下其他工具的痕迹。
    • 更新:手边的例外证明是不可重试的400 - ConditionalCheckFailedException,因此这种怀疑并不适用于此。

如果问题显然是可能导致此问题的原因 - 即使问题说明与您的问题不匹配,Performance issue in 2.0.12.0中的讨论提示ongoing threading issue in the 2.0.x releases .NET SDK,根据手头的使用模式可能会有不同的表现?