无状态 REST API 怎么会有内存泄漏?
How can a stateless REST API have a memory leak?
所以我有一个无状态的 Asp.Net 核心 REST Web API,它似乎有内存泄漏......这对我来说很奇怪,但证据非常有说服力。
这是我的 Azure 门户的屏幕截图,显示 RAM 缓慢上升。
现在我的 API 非常标准...CRUD,大量数据检索...没有很多疯狂的逻辑或任何东西,但它获得了大量的流量(每秒大约 17 个请求一般)。最终服务器到达我必须重新启动它以便释放内存的地步。
下面是一个典型的保存方法...
同样,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);
}
}
好的...所以,万一以后有人遇到这个问题...内存 link 结果证明是配置问题。我过于频繁地实例化配置对象,他们没有被释放...
最终的解决方案是为配置创建一个单例。你可以在这里看到解决方案:
所以我有一个无状态的 Asp.Net 核心 REST Web API,它似乎有内存泄漏......这对我来说很奇怪,但证据非常有说服力。
这是我的 Azure 门户的屏幕截图,显示 RAM 缓慢上升。
现在我的 API 非常标准...CRUD,大量数据检索...没有很多疯狂的逻辑或任何东西,但它获得了大量的流量(每秒大约 17 个请求一般)。最终服务器到达我必须重新启动它以便释放内存的地步。
下面是一个典型的保存方法...
同样,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);
}
}
好的...所以,万一以后有人遇到这个问题...内存 link 结果证明是配置问题。我过于频繁地实例化配置对象,他们没有被释放...
最终的解决方案是为配置创建一个单例。你可以在这里看到解决方案: