C# 微服务内存泄漏,补齐实战

837 阅读1分钟

1. 微服务技术栈

编号技术架构版本作用备注
1CSharp.Net5.0底层编译执行平台开发语言
2GraphQL3.3.1通讯协议服务间接口
3Microsoft.EntityFrameworkCore5.0.3持久层
4Pomelo.EntityFrameworkCore.MySql5.0.0-alpha.2Mysql交互层
5Jaeger0.4.2链路追踪
6MethodBoundaryAspect.Fody2.0.138AOP层.Net AOP相对弱
7Microsoft.Extensions.Diagnostics.HealthChecks5.0.2心跳检查
8Microsoft.Extensions.Logging.Log4Net.AspNetCore5.0.0日志记录
9postjson.com/在线post在线get接口测试

2. 发生现象

2.1 启动内存占有量:111M

2.2 第4次请求结束,内存占有量:946M

可以明显看出占有量前三甲:Redis,Jaeger, Dictionary

2.3 第5次订正、删除请求结束,内存占有量:1G以上

可以明显看出占有量前三甲:Redis,Jaeger, Dictionary

2.4 随着请求量的增加,对内存消耗量不段加大

如何回收内存,释放对象成了重中之重

3.释放对象

3.1 释放Task对象

注意:Task.Run谨慎使用

收集所有Task的点,进行等待执行完毕,如下:

var tasks = new List<Task>();
var task = Task.Run(() =>{
..........
});
tasks.add(task);
//不带参数的返回值
return Task.WhenAll(tasks);
//带参数的返回值
//return Task.FromResult(0);

3.2 释放Linq对象

注意加.AsNoTracking()

from m in dbContext.Set<Item>().AsNoTracking().Where(..

3.3 释放用完的List对象

List<Item> list = new();

....

//使用完后,注意清除对象
}finally{
    list.clear();
}

3.4 释放DBContext对象

//DB上下文定时,注意析构函数
public class AbcDbContext:DbContext{
    public override void Dispose()
    {
        this.Dispose(true);
        GC.Collect();
        GC.SuppressFinalize(this);
    }
}

//调用的类
_abcDbContext.Dispose();
_abcDbContext = null;