【问题标题】:Could this code kill my server?这段代码会杀死我的服务器吗?
【发布时间】:2010-10-18 17:38:13
【问题描述】:

我的网站一直存在问题,它基本上会超时并死掉。我现在已经到了必须将应用程序池设置为每 5 分钟自动回收一次的地步,但即使这样也失败了,因为我刚下班回来,我的电子邮件收件箱里满是 4000 封相同的电子邮件错误。

System.Data.SqlClient.SqlException:超时已过期。在操作完成之前超时时间已过或服务器没有响应。

今天早上我尝试了一个测试,我在连接字符串上禁用了池,这也没有用。

现在我在想,这可能不是连接泄漏的问题,我以前经历过所有这些,我认为这可能与我网站的核心静态属性有关

这是其中之一

public static List<Member> AllMembers
{
    get
    {
        if (HttpRuntime.Cache["Members"] != null)
        {
            return (List<Member>)HttpRuntime.Cache["Members"];
        }
        else
        {
            GetAllMembers();
            return (List<Member>)HttpRuntime.Cache["Members"];
        }
    }
}

每当我想要一个成员列表时都会调用它,你可以看到如果它为 null 则填充缓存,它将使用数据库,如果它不为 null 则返回缓存对象。我也有 SQLCacheDependancy,它将清除这些缓存对象,以便再次填充它们。所以这个属性被称为 ALOT。

现在这是一个网络应用程序,随着我的流量一直在增加,

我的财产可能是原因吗?

非常感谢任何帮助

真吉利

【问题讨论】:

  • 查看 GetAllMembers() 的代码比查看属性更有用
  • 您是否尝试在压力下监控您的应用程序的内存使用情况?您是否检查 MS SQL 上发生的情况并对其进行监控?你如何诊断哪里有问题?或者您只是尝试猜测问题可能出在哪里?

标签: c# performance properties timeout thread-safety


【解决方案1】:

假设您正确处理了所有内容,我有另一种解释:

如果缓存为空/过期并且多个页面尝试同时调用AllMembers,那么每个页面最终可能会同时调用GetAllMembers(),从而降低数据库查询速度。如果调用开始超时,这可能会导致恶性循环。

您可以在代码周围放置lock,因此每个属性只能进行一次数据库查询。以下是我的设置方式:

private static object _allMembersLock = new object();
public static List<Member> AllMembers
{
    get
    {
        lock (_allMembersLock)
        {
            List<Member> members = (List<Member>)HttpRuntime.Cache["Members"];
            if (members == null)
            {
                members = GetAllMembers();
                HttpRuntime.Cache["Members"] = members;
            }
            return members;
        }
    }
}

【讨论】:

  • 最近的编辑现在使您可以调用两次缓存,而且还有一个错误的结束括号。
  • @Adam - 感谢您通知我,我回滚了更改。 @Frank - 当缓存不为空/过期时,您可能试图避免锁定。这是一种合法的方法,但我宁愿将优化排除在这个答案之外。如果他/她认为有必要,OP 可以进行优化。
【解决方案2】:

只是几个常见的嫌疑人:

  1. 您是否正在处理所有 SqlCommand 和读者?

  2. 您是否正在处置/关闭您的 SqlConnection?

  3. 您的数据库是否能够处理负载?那里有性能问题吗?

您帖子中的代码看起来没有问题。

【讨论】:

  • 我唯一的数据库连接是到我的 LINQ 2 SQL 数据上下文,我在每次调用时都在使用:)
  • 你的意思是围绕新的上下文使用?
【解决方案3】:

我在这里看不到任何保护措施来防止对 getter 的多个并发调用触发GetAllMembers。当然,您一次只需要一个线程来加载属性。似乎需要某种lock()

您应该确保刷新缓存的代码也使用相同的lock()

如果可以从多个服务器调用此代码,您还需要确保支持GetAllMembers 的任何数据库端程序逻辑(存储过程或来自客户端的动态 SQL)有效且正确地处理多个并发读取器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-22
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多