我们希望在我们的应用程序和服务之间共享ASP.NET session 状态。我们选择Elasticache / redis来实现这一目标。一切顺利,但我们陷入了僵局。
这是死锁序列:
RedisSessionStateProvider
,在几毫秒内成功获取 session HttpWebRequest
,并附加了ASP.NET_SessionId cookie RedisSessionStateProvider
,它尝试从相同的redis实例获取 session ,并在大约2分钟后超时大概是应用1的
RedisSessionStateProvider
在包含 session 的缓存项上持有(写?)锁。如您所见,我不是Redis专家...AFAICT Elasticache无法让您看到这种情况,只是性能图。
RedisSessionStateProvider
是开源的,所以我不能在那儿戳。我还尝试获取
RedisSessionStateProvider
记录(通过loggingClassName
参数),但是App 1或App 2都没有写入任何内容(尽管我的Log()
方法被调用)。为了证明这是
RedisSessionStateProvider
死锁(而不是我们自己的代码死锁),我将App 1切换回使用InProc session ,并且一切正常。有没有人有什么建议?顺便说一句,我们的Session数据在所有意图和目的上都是不可变的,因此确实不需要锁定它。
非常感谢,
皮特
编辑:根据要求的sessionState配置。请注意,较大的
operationTimeoutInMilliseconds
值是为了避免在调试应用程序时出现异常。生产时将更改为〜5000。 <sessionState mode="Custom" customProvider="RedisSessionProvider">
<providers>
<add name="RedisSessionProvider"
type="Microsoft.Web.Redis.RedisSessionStateProvider"
host = "ec2-184-73-3-249.compute-1.amazonaws.com"
port = "6379"
ssl = "false"
throwOnError = "true"
retryTimeoutInMilliseconds = "2000"
applicationName = "PE"
connectionTimeoutInMilliseconds = "2000"
operationTimeoutInMilliseconds = "1800000"
</providers>
</sessionState>
最佳答案
在页面asp.net页面执行生命周期开始时,它将调用GetItemExclusive,它从存储中获取 session (在本例中为redis)并锁定该 session ,以便其他并行请求无法在此请求工作时修改 session 。该锁定具有与您可以使用web.config设置的请求超时等效的超时,如下所示。
<configuration>
<system.web>
<httpRuntime executionTimeout="10"/>
</system.web>
</configuration>
现在,页面将执行,并根据天气情况在 session 中进行了任何修改或未修改的操作,它调用SetAndReleaseItemExclusive或ReleaseItemExclusive来释放锁定。如果此请求由于某种原因失败,它将根据retryTimeoutInMilliseconds值重试。如果retryTimeoutInMilliseconds与operationTimeoutInMilliseconds很小或相同,则它可能根本不重试。如果SetAndReleaseItemExclusive或ReleaseItemExclusive未成功完成,则基本上您的 session 将锁定您在上面设置的“executionTimeout”的完整时间(以秒为单位)。所有其他请求都将被阻止,并且在 session 被锁定时将无法访问。锁到期时将自动释放。
使用web.config属性loggingClassName和loggingMethodName来配置日志记录。升级到以上软件包时,您可以在web.config注释中找到更多详细信息。您基本上可以提供一个公共(public)的静态方法,该方法返回TextWriter。 session 状态提供程序和StackExchange.Redis.StrongName都将使用此TextWriter对象记录详细信息。
这将帮助我们获得有关问题的更多详细信息。请注意,启用日志记录会降低性能。
使用日志记录的示例:
namespace SSPWebAppLatest3
{
public static class Logger
{
public static TextWriter GetLogger()
{
return File.CreateText("C:\\Logger.txt");
}
}
}
Web.config:
<add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="127.0.0.1" accessKey="" ssl="false"
loggingClassName="Logger, SSPWebAppLatest3, Version=1.0.0.0, Culture=neutral ……."
loggingMethodName="GetLogger"/>
请寄给我一个可重现的测试应用程序,以便进一步调试它。您还可以执行与 session 状态相同的操作,并且输出缓存提供程序代码现在是开源的。 (https://github.com/Azure/aspnet-redis-providers)
关于asp.net - RedisSessionStateProvider Elasticache死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30082609/