AWS Dynamo DB 作为 ASP.NET 会话提供程序时出现 400 错误请求

tuc*_*caz 5 session session-state amazon-web-services asp.net-mvc-4 amazon-dynamodb

我们在应用程序中使用AWS 的 DynamoDB Session Provider来存储会话数据。

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

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

我收到 (400) 错误请求,似乎是在 1 或 2 分钟内发出的所有呼叫,每小时发生 3 或 4 次。

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

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
Run Code Online (Sandbox Code Playgroud)

从下面的时间图中我们可以看到,所有请求在大部分时间内都正常(图 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"
}
Run Code Online (Sandbox Code Playgroud)

回复:


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"
}
Run Code Online (Sandbox Code Playgroud)

图1

非 Web 事务 - 图 1

图2

错误 - 图 2

任何帮助表示赞赏。谢谢!

小智 4

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

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

这些错误不应上升到应用程序级别。适用于 .NET 的 AWS 开发工具包会因条件更新失败而引发异常,会话提供商将其解释为获取锁定失败。该信息被传回 ASP.NET 框架,该框架对请求进行排队,直到获得锁为止:

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