的问题

你好,

一个小小的背景在我问题...我现在有一个网站建立于ISP我的工作,显示信息的用户根据其计费状况。当他们在不支付我显示的一个非支付的消息,如果他们在虐待,我显示的一个滥用信息等。业务是由思科常设专家委员会,重定向最终用户HTTP交到我的网站。

这个问题,我看到的是过高的交通。我相信交通可能是P2P业务、自动更新,或任何其他排序。基本上,任何使用口80是重新定向常设专家委员会到我的网页。

该解决方案我在试图执行我的服务器上是一个模块,区块用户根据其打算。因此,如果他们超过阈值在一定的时间期限,它们将被重新定向到另一个网页,其中将希望带来的负荷断的处理,因为它不需要做所有的SQL查和情报,发生在ASP.NET 页。

然而,当我试图强制执行的一个模块,我建成,它实际上具有相反的结果(增加CPU载)。本模块采用一个中存表,保存在应用国家其它用于追踪的要求,由知识产权。这里是代码,用于该模块:

public class IpHitCount : IHttpModule
{
    const string tableKey = "appIpLog";

    #region IHttpModule Members

    public void Dispose()
    {

    }

    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += new EventHandler(checkHitCount);
    }

    #endregion

    private void checkHitCount(object sender, EventArgs e)
    {
        // Cast the parameter into a HttpApp object
        HttpApplication app = (HttpApplication)sender;

        // make sure that this is the user's first request for the app
        // (all first requests are routed through main)
        if (app.Request.Url.AbsolutePath.ToLower().Contains("main.aspx"))
        {
            // If the in memory table does not exist, then create it
            if (app.Application[tableKey] == null)
            {
                app.Application[tableKey] = CreateTable();
            }

            DataSet ds = (DataSet)app.Application[tableKey];
            DataTable tbl = ds.Tables["IpTable"];
            DeleteOldEntries(tbl);

            string filter = string.Format("ip = '{0}'", app.Request.UserHostAddress);
            DataRow[] matchedRows = tbl.Select(filter);

            if (matchedRows.Length > 0)
            {
                DataRow matchedRow = matchedRows[0];
                if ((int)matchedRow["hitCount"] > 4)
                {
                    app.Response.Redirect("HitCountExceeded.htm", true);
                }
                else
                {
                    matchedRow["hitCount"] = (int)matchedRow["hitCount"] + 1;
                }
            }
            else
            {
                DataRow newEntry = tbl.NewRow();
                newEntry["timestamp"] = DateTime.Now;
                newEntry["hitCount"] = 1;
                newEntry["ip"] = app.Request.UserHostAddress;
                tbl.Rows.Add(newEntry);
            }                
        }
    }

    private DataSet CreateTable()
    {
        DataSet ds = new DataSet();
        DataTable table = new DataTable("IpTable");

        DataColumn col1 = new DataColumn("timestamp", typeof(DateTime));
        col1.AutoIncrement = false;
        col1.DefaultValue = DateTime.Now;
        col1.ReadOnly = false;
        col1.Unique = false;

        DataColumn col2 = new DataColumn("ip", typeof(string));
        col1.AutoIncrement = false;
        col1.ReadOnly = false;  
        col1.Unique = false;

        DataColumn col3 = new DataColumn("hitCount", typeof(int));
        col1.AutoIncrement = false;
        col1.ReadOnly = false;
        col1.Unique = false;

        table.Columns.Add(col1);
        table.Columns.Add(col2);
        table.Columns.Add(col3);

        ds.Tables.Add(table);

        return ds;
    }

    private void DeleteOldEntries(DataTable tbl)
    {
        // build the where clause
        string filter = "timestamp < '" + DateTime.Now.AddMinutes(-5.0).ToString() + "'";

        // run the query against the table
        DataRow[] rowsToDelete = tbl.Select(filter);

        // individually delete each row returned
        foreach (DataRow row in rowsToDelete)
        {
            row.Delete();
        }
    }
}

所以我想知道的是如下:有什么是你可以看到,我做错了的模块,这可能会造成利用率高的中央处理器?是否有替代办法,我应该阻止这个交易?

任何帮助可以提供将不胜感激。

谢谢, C


解决方案

我已经改变中的代码模块只运行的删除部分中每一个1分钟:


    if (app.Application[deletedKey] == null)
    app.Application[deletedKey] = DateTime.Now;

    DateTime deletedDate = (DateTime)app.Application[deletedKey];

    if (DateTime.Now >= deletedDate.AddMinutes(1))
    {
        DeleteOldEntries(tbl);
        app.Application[deletedKey] = DateTime.Now;
    }

我还添加了一些代码,我认为索引的IP列的我的数据集。它似乎不正确的,所以我不能肯定它是做什么的,我打算要做的:


    DataColumn[] key = new DataColumn[1];
    key[0] = col1;

    table.PrimaryKey = key;

    ds.Tables.Add(table);

后两个以上的变化,CPU载似乎已经大幅下降。我想,我们SQL服务器也是感谢上帝,现在它终于可以呼吸。

谢谢你的帮助!

有帮助吗?

解决方案

有一两件事,我会尝试:

  • 我看到的第一件事情是,你打电话的"DeleteOldEntries"子每次这个代码运行,这会导致它来做一个扫描通过整个数据表,在每一个通过。是否有另一种方法,你可能会限制本来只在某些时候?如果没有一个计时器,运行它每15秒,然后也许有第二个变量的国家(如"ExecCount")增加每一次"CheckHitCount"是运行,所以,你只清除每10或20时通过?这种方式,可以避免这种潜在贵部的代码在每个运行。
  • 另一个选择是加入一个索引到你的数据表。我不知道如何。净处理查找数据表,但是也许这会对你感兴趣: MSDN文章

你可以用的东西像蚂蚁一样剖析,看看那里的大多数时间都花在执行?因为我想这页就是被称为很多很多次,你可以任何方式降低的影响,甚至有点会有很大的不同。

如果你获得一些成果,但仍然不满意,确保修改你的问题添加新的信息,以便我们可以继续努力实现一个解决方案,你很高兴。

其他提示

好吧,你必须记住DataSet将在内存中,并且要搜索DataSet,它将花费大量的CPU周期来查找你正在寻找的记录。

除此之外,由于这是一个Web应用程序,因此您将获得大量的点击,因此您最终会非常频繁地调用此例程。

我的建议是将命中计数存储在数据库服务器中,然后更新并查询服务器以查看是否超过了命中计数。它将能够处理负载,并处理您要查询的数据集的大小。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top