【问题标题】:How can a stateless REST API have a memory leak?无状态的 REST API 怎么会有内存泄漏?
【发布时间】:2018-02-07 00:34:43
【问题描述】:

所以我有一个无状态的 Asp.Net Core REST Web API,它似乎有内存泄漏......这对我来说似乎很奇怪,但证据非常有说服力。

http://prntscr.com/ge9k2l

这是我的 Azure 门户的屏幕截图,显示 RAM 缓慢上升。

现在我的 API 非常标准...... CRUD,大量数据检索......不是很多疯狂的逻辑或任何东西,但它获得了大量的流量(平均每秒大约 17 个请求)。最终服务器到达我必须重新启动它以便释放内存的地步。

下面是一个典型的Save方法...

再次重申,API 是无状态的,因此我不会真正缓存或保留任何数据...只需做我必须做的事情并返回数据。

想法?

    [HttpPost]
    public IActionResult Save([FromBody]QuizViewModel quiz)
    {
        if (ValidateAdmin() == null)
            return StatusCode(401);

        try
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            Quiz dbQuiz = null;

            if (quiz.ID == new Guid())
            {
                LogInfo("Saving new quiz: Name [" + quiz.Name + "]");

                // new 
                dbQuiz = new Quiz();
                dbQuiz.ID = Guid.NewGuid();
                dbQuiz.CreatorID = quiz.CreatorID;
                dbQuiz.CreateDate = DateTime.UtcNow;
                _quizRepository.Add(dbQuiz);
            }
            else
            {
                LogInfo("Updating quiz: ID [" + quiz.ID + "], Name: [" + quiz.Name + "]");
                // update
                dbQuiz = _quizRepository.GetSingle(x => x.ID == quiz.ID, y => y.Questions);
                dbQuiz.UpdateDate = DateTime.UtcNow;
                dbQuiz.UpdaterID = quiz.CreatorID;
            }

            _quizRepository.ManageQuestions(dbQuiz, quiz.Questions);

            dbQuiz.Name = quiz.Name;
            dbQuiz.LessonID = quiz.LessonID;
            dbQuiz.Instructions = quiz.Instructions;
            dbQuiz.ImagePath = quiz.ImagePath;
            dbQuiz.VideoPath = quiz.VideoPath;

            _quizRepository.Commit();

            quiz = Mapper.Map<Quiz, QuizViewModel>(dbQuiz);

            CreatedAtRouteResult result = CreatedAtRoute("Save", new { controller = "Quiz", ID = quiz.ID }, quiz);

            LogInfo("Quiz saved: ID [" + dbQuiz.ID + "]");
            return new OkObjectResult(result);
        }
        catch (Exception ex)
        {
            HandleError(ex);
            return BadRequest(ex);
        }
    }

【问题讨论】:

  • 你不能确定这是内存泄漏,如果垃圾收集器有足够的资源,它可以决定不删除对象。在每次返回之前添加 GC.Collect() 并再次进行测试。
  • 另外,除非您发布完整的 api,否则无法确定是否存在内存泄漏,因为您只显示 api 中的一个功能。
  • 程序最终会崩溃还是抛出异常?你可以创建一个转储文件并检查所有内存的使用情况吗?从您的屏幕截图来看,它看起来并没有显着增加。
  • 无状态是指客户端/服务器之间的请求和响应,而不是“服务器永远不会保留任何东西”。如果您有 DI(由于它是 webapi 而您这样做),并且 DI 持有对从请求返回的对象的引用,它可能会在内存中建立,即使应用程序仍然是“无状态的”。正如@Gusman 所说,从一小段代码中确定泄漏位置并不容易。
  • 我不认为你们都想要我的完整 API :) 我包含了 sn-p 只是为了了解我们的调用类型。 @xela 是的,最终服务器将耗尽内存并崩溃......大约需要一天时间。数据转储是个好主意。会这样做并报告。谢谢。

标签: c# memory-leaks asp.net-core-webapi


【解决方案1】:

好的...所以,如果将来有人遇到这种情况...内存链接原来是配置问题。我过于频繁地实例化配置对象并且它们没有被放开......

最终的解决方案是为配置创建一个单例。您可以在此处查看解决方案:

ASP.Net Core 2 configuration taking up a lot of memory. How do I get config information differently?

【讨论】:

    猜你喜欢
    • 2011-08-09
    • 2018-07-27
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多