IIS工作进程使用ASP.NET MVC网站在Web服务器上使用6gb RAM

时间:2017-06-26 15:09:01

标签: asp.net entity-framework memory-leaks

我有一个在自己的应用程序池(IIS 8)中运行的网站。池的设置是默认设置,即每29小时回收一次。

我们的网络服务器只有8GB内存,我注意到这个网站的工作进程经常爬到6GB内存并使服务器慢慢爬行。这是当前Web服务器上唯一的站点。

我也安装了SQL Express 2016。该网站使用的是EF版本6.1.3。

MVC网站非常简单。它有一个GETPDF控制器,它在表中找到一行,获取存储在字段中的PDF信息,然后按如下方式将其提供给浏览器: -

using (eBillingEntities db = new eBillingEntities())
{
try
{
    string id = model.id;
    string emailaddress = Server.HtmlEncode(model.EmailAddress).ToLower().Trim();  

    eBillData ebill = db.eBillDatas.ToList<eBillData>().Where(e => e.PURL == id && e.EmailAddress.ToLower().Trim() == emailaddress).FirstOrDefault<eBillData>();

    if (ebill != null)
    {

        // update the 'Lastdownloaded' field.
        ebill.LastDownloaded = DateTime.Now;
        db.eBillDatas.Attach(ebill);
        var entry = db.Entry(ebill);
        entry.Property(en => en.LastDownloaded).IsModified = true; 
        db.SaveChanges();


        // Find out from the config record whether the bill is stored in the table or in the local pdf folder.
        //
        Config cfg = db.Configs.ToList<Config>().Where(c => c.Account == ebill.Account).FirstOrDefault<Config>();

        bool storePDFDataInEBillTable = true;

        if (cfg != null)
        {
            storePDFDataInEBillTable = cfg.StorePDFDataInEBillDataTable;
        }
        // End of Modification

        byte[] file;

        if (storePDFDataInEBillTable)
        {

            file = ebill.PDFData;
        }
        else
        {

            string pathToFile = "";

            if (string.IsNullOrEmpty(cfg.LocalPDFDataFolder))
                pathToFile = cfg.LocalBackupFolder;
            else
                pathToFile = cfg.LocalPDFDataFolder;

            if (!pathToFile.EndsWith(@"\"))
                pathToFile += @"\";

            pathToFile += ebill.PDFFileName;

            file = System.IO.File.ReadAllBytes(pathToFile);

        }

        MemoryStream output = new MemoryStream();

        output.Write(file, 0, file.Length);
        output.Position = 0;

        HttpContext.Response.AddHeader("content-disposition", "attachment; filename=ebill.pdf");

        return new FileStreamResult(output, "application/pdf");
    }
    else
        return View("PDFNotFound");

}
catch
{
    return View("PDFNotFound");

}

这里有没有内存泄漏?

文件字节数组和内存流是否会被释放?

另外,关于清理实体框架引用,还有什么需要做的吗?

如果代码看起来不错,哪里开始寻找好的地方?

此致

2 个答案:

答案 0 :(得分:0)

  

这里有没有内存泄漏?

没有

  

文件字节数组和内存流是否会被释放?

最终,是的。但这可能是你过度记忆的原因。

  

另外,关于清理实体框架引用,还有什么需要做的吗?

没有

  

如果代码看起来不错,哪里开始寻找好的地方?

如果此代码是高内存使用的原因,那么因为您正在将文件加载到内存中。并且你要在内存中加载每个文件的两个副本,一个在byte []中并复制到MemoryStream。

没有必要这样做。

要消除文件的第二个副本,请使用MemoryStream(byte[])构造函数,而不是将字节[]中的字节复制到空的MemoryStream。

要消除内存中的第一个副本,您可以将数据流式传输到将成为FileStreamResult目标的临时文件中,或使用ADO.NET流初始化FileStreamResult。

请参阅https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sqlclient-streaming-support

如果您转到ADO.NET流式传输DbContext,则需要将其范围限定为Controller,而不是局部变量,这在任何情况下都是一种很好的做法。

答案 1 :(得分:0)

除了大卫的建议。我注意到我正在做以下

**db.eBillDatas.ToList<eBillData>()**

因此我从数据库中获取了所有数据然后再次使用where子句获取数据。

在数据库开始填满之前,我没有注意到这个问题。

我删除了那部分,现在IIS工作者处理大约是100mb。