EFcore多线程查询,该怎么解决内存泄漏的问题


 昨天在园子里提了一个EFcore多线程查询导致服务内存飙升的问题,现在依然还没有找到解决办法,今天把问题详细的陈述一遍。

刚开始发现问题是公司一个服务的内存飚到了7个G,系统直接杀死了这个进程,后面发现问题是随着高并发的访问,里面的EFcore进行大量数据查询,在访问结束后内存没有释放干净,内存不断的堆积,服务直接就崩了。然后我在本地用例还原了这个过程,大致如下:

GRPC服务端:

(一开始怀疑是DatabaseContext注入的问题,用了AddScoped;AddTransient;后者直接用using都没有解决问题,所以不是这个问题)

在GRPC里一个方法SayHello查询一张表的数据(数据大概1w多)

public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
var d = efoscoreContext.Project.Where(w => w.ProjectId > 15).Select(s => new 
{

*******
}).ToList();
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}

客户端:

每三秒调一次Grpc的SayHello方法,后面发现GRPC服务里确实释放不完内存,随着访问的次数的增加,内存会堆积到一个很高的值,如果内存抗不住就崩了

while (true)
{
for (int i = 1; i < 40; i++)
{
reply = client.SayHello(new FirstGrpc.HelloRequest() { Name = "" });
}
Thread.Sleep(TimeSpan.FromSeconds(3));
}

过程会进行GC,但是还会剩下大量的内存没GC完,而且会累积到很高。

后面思考,GRPC服务以线程池的方式响应请求,会不会是Efcore在多线程里出现了问题的原因

后面我用控制台做了一个测试,发现问题确实是这样,Efocore在多线程查询,线程结束后,内存并没有回收完

多线程Efocore查询用例:

先顺序执行:

while (true)
{
for (int i = 1; i < 100; i++)
{
ProjectQuery()//执行efocore查询
;
}
Thread.Sleep(TimeSpan.FromSeconds(5));
}

顺序执行没有任何问题,内存占用是很正常的也就一直100多M

多线程执行:

while (true)
{
for (int i = 1; i < 100; i++)
{
 var t = new Task(() => ProjectQuery()//执行efocore查询
);
t.Start();
}
Thread.Sleep(TimeSpan.FromSeconds(5));
}

多线程执行一上来就飚到了2G,后面会剩下1.2g一直在那里,再后面就会1-4M的累积,累积


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM