Web API 2.0接口内存泄漏求助:调用后内存未释放持续增长
我来帮你拆解一下这个内存持续增长的问题,从你给出的代码片段来看,几个关键的写法问题直接导致了内存泄漏:
1. 每次请求重复创建MongoClient实例是核心问题
你在Post方法里只要Token匹配,就会新建一个MongoClient对象,但MongoClient的设计是必须单例复用的——它内部维护着MongoDB的连接池,频繁创建新实例会带来两个致命问题:
- 每个新的MongoClient都会初始化独立的连接池,旧实例的连接池资源无法被及时回收,大量闲置连接占用内存
- 大量MongoClient实例本身会堆积在内存中,如果Controller实例因为某些原因(比如异步操作未完成、上下文引用)没被GC及时回收,这些MongoClient对象也会跟着滞留
2. 类级字段的不必要持有加剧了内存占用
你的__db、__docs、__docsColl都是Controller的实例字段,每次请求进入Token分支都会重新赋值,但旧的数据库、集合对象仍然被之前的Controller实例引用(如果Controller没被及时回收的话)。尤其是__docs作为BsonDocument,完全没必要放在类级别,改成方法内的局部变量会让它在请求结束后立刻被标记为可回收。
3. 缺少资源复用的规范
MongoDB .NET驱动的大部分资源是托管的,但频繁创建的MongoClient会持有非托管的连接资源,这些资源如果没有通过单例复用的方式被合理管理,就会持续占用内存,无法被GC释放。
具体修复方案
第一步:单例化MongoClient
把MongoClient的创建移到静态构造函数或者应用启动时,确保整个应用生命周期只创建一次:
public class LogsController : ApiController { // 静态单例MongoClient,整个应用只初始化一次 private static readonly IMongoClient _mongoClient; private readonly IMongoDatabase _db; private readonly IMongoCollection<BsonDocument> _docsColl; static LogsController() { _mongoClient = new MongoClient(new MongoClientSettings { Server = new MongoServerAddress("serverIP", 27017), Credentials = new[] { MongoCredential.CreateCredential("database", "user name", "password") } }); } public LogsController() { // 从单例Client获取数据库和集合,复用连接池 _db = _mongoClient.GetDatabase("connect_database"); _docsColl = _db.GetCollection<BsonDocument>("I..."); } [Route("api/Logs")] public async Task<int> Post(RequestData logs) { if (logs.Token == "I") { // 把BsonDocument改成局部变量,请求结束后自动回收 var docs = new BsonDocument() { { "Customer", logs.Customer } }; // 这里执行你的数据库操作,比如 await _docsColl.InsertOneAsync(docs); return 1; // 返回操作结果,根据实际情况调整 } // 其他Token分支的逻辑 return 0; } }
第二步:清理不必要的类级字段
把原来的__docs改成方法内的局部变量,避免Controller实例持有不必要的对象引用。
第三步:确认Controller生命周期
确保你的Controller是默认的**Transient(每次请求创建)**生命周期,如果被错误配置成Singleton,Controller实例会一直驻留内存,它持有的所有数据库相关对象也不会被回收,这会导致更严重的内存泄漏。
额外排查建议
如果修复后还有内存增长问题,可以用Visual Studio的内存诊断工具捕获内存快照,查看哪些对象在持续堆积——重点关注Mongo相关的对象(比如MongoClient、MongoDatabase、连接池相关的MongoConnectionPool等),确认是否还有未被正确回收的资源。
内容的提问来源于stack exchange,提问作者Ebg Test

